9

以下のコード スニペットでは、doThings() メソッドを static として宣言すると、クラスがスレッド セーフになります。この理由は、複数の TestSeven スレッドが開始され、x が静的変数であるため、競合状態が発生する可能性があるためですか?

public class TestSeven extends Thread{

    private static int x;

    public synchronized void doThings(){
        int current = x;
        current++;
        x = current;
    }

    public void run(){
        doThings();
    }

    public static void main(String args[]){
        TestSeven t = new TestSeven();
        Thread thread = new Thread(t);
        thread.start();
    }
}
4

5 に答える 5

16

はい、正確に。のsynchronized性質上、同じインスタンスでdoThings複数のスレッドによって同時に呼び出されることはありません。変数はインスタンスごとではなくグローバルに共有されるため、安全ではありません。x

現実の世界では、いくつかのドアがあるバスルームと考えてください。誰かが 1 つのドアを開けてロックすることはできますが、他の誰かが別のドアから入ってくるのを止めることはできません...

于 2011-11-25T11:15:14.950 に答える
1

メソッドdoThings staticを宣言すると、インスタンスロックではなくクラスロックで同期されるため、防弾になります。

于 2011-11-25T11:17:37.207 に答える
1

はい。これで競合状態が発生する可能性があります。メソッドを変数ではなく同期させているためです。したがって、競合状態の定義によれば、あるスレッドが変数の値を読み取り、同期されたメソッドの他のスレッドがそれを書き込むことができます。したがって、競合状態が発生します。

于 2011-11-25T11:18:17.650 に答える
1

でコードを同期しますthis。つまり、TestSeven のそのインスタンスで同期します。x静的なので、ロックされません。そのため、異なるインスタンスから同じ にアクセスできますx。その属性のロックを解除するには、クラスを同期する必要があります。

于 2011-11-25T11:20:59.920 に答える
1

メソッドが静的でない場合、各 TestSeven オブジェクトは独自のロックを使用して同期すると思います。したがって、ロックごとに 1 つのスレッドがあり、別のスレッドを待つ必要はありません。メソッドが静的であると宣言されている場合、対応する Class オブジェクトをロックしていることを思い出すようです。

于 2011-11-25T11:16:00.383 に答える