2013-08-31 104 views
1

我想兩個線程共享的變量,但有時在運行時它打印出2次,而不是1和2線程共享實例變量

public class man implements Runnable{ 

    int value = 0; 

    public static void main(String[] args){ 
     Runnable job = new man(); 
     Thread work1 = new Thread(job); 
     work1.setName("Thread1"); 
     Thread work2 = new Thread(job); 
     work2.setName("Thread2"); 

     work1.start(); 
     work2.start(); 
    } 


    public void run(){ 
     synchronized(this){ 
      value = value + 1; 
     } 
     System.out.println("VALUE = " + value +", Running " + Thread.currentThread().getName()); 
    } 



} 

輸出有時是:

VALUE = 2, Running Thread2 
VALUE = 2, Running Thread1 

等次是:

VALUE = 1, Running Thread2 
VALUE = 2, Running Thread1 

這究竟是爲什麼?我在HeadFirst的書中學習Java,這個問題出現了。

回答

3

您不會同步System.out.println調用中的訪問,所以偶爾「第二個」線程會在「第一個線程」打印之前遞增。

+0

哦,不錯,謝謝你的提示。 –

3

您需要同步對變量的訪問。

發生了什麼事情是兩個線程都讀取變量的值後,都增加了它。換句話說:

  1. 線程1:syncronized(本)=>線程2不能進入到它自己的syncronized(本)
  2. 線程1:值=值+ 1; =>說1個
  3. 線程1:完syncronized塊=>線程2可以進入其自己的syncronized(本)現在
  4. 線程2:syncronized(本)=>線程1不能進入到它自己的syncronized(這個)
  5. 線程2:value = value + 1; => 2
  6. 線程2:打印值,即2
  7. 線程1:打印值,即2

的解決方案是移動System.out.println("VALUE = " + value +", ...);的​​塊內。這迫使上述重新排序序列的成:

  1. 線程1:syncronized(本)=>線程2不能進入到它自己的syncronized(本)
  2. 線程1:值=值+ 1; =>說1個
  3. 線程1:打印值,即1
  4. 線程1:完syncronized塊=>線程2可以進入其自己的syncronized(本)現在
  5. 線程2:syncronized(本)=>線程1不能進入它自己的同步(this)
  6. 線程2:value = value + 1; => 2
  7. 線程2:打印值,即2