2011-11-25 16 views
8

以下のコードスニペットでは、doThings()メソッドを静的として宣言すると、クラスがスレッドセーフになります。この理由は、複数の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(); 
    } 
} 
+1

Btwは、スレッドであるTestSevenをThreadコンストラクタの引数として渡します。これはThread IS-A Runnableのために機能しますが、推奨されていません。TestSevenがRunnableを実装するようにしてください。 –

答えて

15

はい、正確です。​​という性質のdoThingsは、同じインスタンス上で複数のスレッドによって同時に呼び出されるのを停止します。変数xは、グローバルベースで共有され、インスタンスごとではないため、安全ではありません。現実の世界の用語では

は、いくつかのドア付きのバスルームと考える - 誰かがそれをロックし、その後一つの扉を開くことができ、それは...別のドアを経由して入ってくるから、他の誰かを停止しません

+1

非常に良い例です。 – gprathour

+0

+1:現在のスレッドでのロックは、ほとんどの場合、無意味です。 –

+0

非常に良い説明。簡単にまとめていますが、うまくまとめています。 –

1

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

1

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

1

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

1

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

関連する問題