2016-07-08 1 views
2

私は次のコードを持っている:Javaの同期スレッド値の更新方法

boolean signal; 

@Test 
public void test() throws InterruptedException { 
    Thread thread = new Thread(new Runnable() { 
     @Override 
     public void run() { 
      while (!signal){ 
       // empty loop body 
      } 
     } 
    }); 
    thread.start(); 
    Thread.sleep(1000); 
    signal = true; 
    thread.join(); 
} 

それはスレッドでsignal変数のローカルコピーの作成による無限ループを実行します。 signal変数をvolatileにすることで修正できることはわかっています。

boolean signal; 

@Test 
public void test() throws InterruptedException { 
    Thread thread = new Thread(new Runnable() { 
     @Override 
     public void run() { 
      while (!signal){ 
       synchronized (this) { 

       } 
      } 
     } 
    }); 
    thread.start(); 
    Thread.sleep(1000); 
    signal = true; 
    thread.join(); 
} 

を​​は、スレッド内の私のsignal値を更新する方法:(でも空の)私のループ内​​ブロックを追加した場合だけでなく、ループが正常に終了することができますか?

+2

2つ目のプログラムが決して終了しないようにするには、合法的です。JVM/CPUアーキテクチャは、JLSが要求するよりも強力なメモリモデルを適用するようです。 – assylias

+0

面白い読み込み:https://shipilev.net/blog/2016/close-encounters-of-jmm-kind/ –

+1

彼は、https://shipilev.net/blog/2016/close-encounters- of-jmm-kind /#wishful-unobserved-sync – assylias

答えて

1

Synchronizedはシグナル値自体を更新しませんが、基本的には2つのスレッドが同じオブジェクトを同時に使用しないようにするために2つのフラグを設定します。 MonitorEnterとMonitorExitのようなものです。

最初のオブジェクトがオブジェクトをロックし、2番目のオブジェクトが解放されます。

次の記事をご覧ください:how-the-java-virtual-machine-performs-thread-synchronization

記事が非常に古くなっています。しかし、私が理解する限り、後ろの論理は残っています。

+0

私はそれを知っていますが、同期化されたブロックをループに追加するのがなぜ私の2番目の例でシグナル変数を更新するのですか? – Cortwave

+0

同期されていないものは利己的なスレッドなので、その意味は;それは仕事が終わるまで止まるでしょう。ループ内に収穫/スリープ/ブロックなどのI/O操作がない場合、スレッドは自己好きなスレッドになる可能性があります。 今、同期を設定すると、利己的でないスレッドをブロックしているので、オブジェクト "信号"の操作 動作自体は、実行するインフラストラクチャによって大きく異なります。しかし、基本的には2つのスレッドがあります。1)メインスレッド2)スレッドと2つ目は利己的なので、メインには続かせません。 –