2017-05-12 16 views
1
public class Main { 

    public static void main(String[] args) { 
     Status status = new Status(); 
     new Thread(new Runnable() { 
      @Override 
      public void run() { 
       status.setStatus(true); 
      } 
     }).start(); 
    } 
} 

class Status { 
    boolean status = false; 
    public void setStatus(boolean status) { 
     this.status = status; 
    } 
    public boolean getStatus() {return status;} 
} 

作成されたスレッドがメインスレッドの状態オブジェクトを共有しています.CPUキャッシュ、メインスレッド、および作成されたスレッドのステータスオブジェクトを作成すると、スレッドセーフではないと思います-threadコール 'setStatus'メソッドは、キャッシュデータのみを更新し、メインスレッドは更新されたデータを現在見ることができません。したがって、同期が必要です。私は正しく理解していますか?Javaの匿名の内部クラスがRunnableと共有の外部クラスオブジェクトを実装するのはスレッドセーフですか?

答えて

3

発生前ルールについては、jls 17.4.5を参照してください。

開始されると、開始されたスレッド内のアクションの前に発生します。したがって、新しいスレッドは、メインスレッドで作成された状態オブジェクトを表示します。

ステータスの変更は、メインスレッドには表示されないことが保証されています。メインスレッドが新しいスレッドに参加する場合は、発生前ルールが適用され、新しいスレッドが完了すると変更が表示されます。新しいスレッドを終了させずに変更を表示したい場合は、ブール値をvolatileにするか、その型を AtomicBooleanに変更することができます。あるいは、setterとgetterの両方にsynchronizedキーワードを設定します。

JVMは、これを表示しないように要求されているわけではありませんが、必須ではありません。 jvmの実装に応じてYmmv。

あなたのご理解は正しいと思います。

+0

あなたが言ったことに加えて、そのコードをスレッドセーフにするには、 'boolean status'変数を' volatile'として宣言する必要があります。 –

+1

@パヴロ:それはうまくいくでしょう。複数の方法があります。しかし、Thread.joinを使用すれば十分です。 –

関連する問題