6

私のクラスはスレッドセーフですか?そうでない場合はなぜですか?

class Foo {
 boolean b = false;

 void doSomething() throws Exception {
    while (b) Thread.sleep();
 }

 void setB(boolean b) {
     this.b = b;
 }
}
4

5 に答える 5

10

実行中のスレッドは、コードがコンパイルされるまで(後でランダムな時点になる可能性があります)変更が表示され、変更が表示されなくなる可能性があるため、コードはスレッドセーフではありません。

ところで:これはテストを行うのを非常に難しくします。たとえば、1秒間寝ると、この動作が3時間近く見られない場合があります。

つまり、機能する場合と機能しない場合があり、機能したからといって機能し続けるとは言えません。


JITは最適化できbないため、最適化できます。volatile

while (b) Thread.sleep(N);

することが

boolean b = this.b;
if (b) while (true) Thread.sleep(N);

したがって、の値はb毎回読み取られるわけではありません。

于 2012-10-01T14:19:34.860 に答える
7

そうではない。インスタンス変数値をsetB()更新していますが、ではありません。bsynchronized

複数のスレッドがsetB()同時にメソッドを実行しようとすると、予期しない結果が生じる可能性があります。

オブジェクトをロックsynchronizeするメソッド(または)を使用する必要があります。synchronizethis

于 2012-10-01T14:17:04.143 に答える
5

AtomicBooleanを見てください。これは、一度に1つのスレッドのみがアクセスできることを意味します。

于 2012-10-01T14:20:41.200 に答える
3

しかし、それはスレッドセーフとどのように関係していますか?少し混乱しました。

「スレッドセーフ」の定義に戻ります。ウィキペディアはこれを言います:

「スレッドセーフは、マルチスレッドプログラムのコンテキストに適用できるコンピュータプログラミングの概念です。複数のスレッドによる同時実行中に正しく機能する場合、コードの一部はスレッドセーフです。」

ここで重要なのは、正しく機能することです。Peter Lawreyによって説明されたシナリオを見ると、JITコンパイルにより、値がからにb変更されたときに気付かず、代わりに永遠にループするコードが生成される可能性があることがわかります。これは明らかに間違った動作です。また、これは2つのスレッドがある場合にのみ発生するため、スレッドセーフの問題です。truefalse

于 2012-10-01T15:10:44.640 に答える
0

ここで問題となる概念は可視性であり、並行Javaで説明されています。doSomething()が別のスレッドで実行されている場合、JVMは、setBで実行されたアクションがdoSomethingが認識するバージョンbに適用されることを保証しません。したがって、setBを呼び出すことができ、doSomethingが終了することは保証されません。

于 2012-10-01T14:19:01.677 に答える