2013-05-10 67 views
1

大家好我有這樣的代碼:爲什麼這不正確同步?

public class ThreadTester { 
    public static void main(String args[]) { 
     Counter c = new Counter(); 
     for (int i = 0; i < 10; i++) { 
      MyThread a = new MyThread(c); 
      MyThread b = new MyThread(c); 
      a.start(); 
      b.start(); 
     } 
     System.out.println("The value of the balance is " + c.getVal()); 
    } 
} 

class MyThread extends Thread { 
    private Counter c; 
    public MyThread(Counter c){ this.c = c; } 
    public void run(){ s.increment(); } 
} 

class Counter { 
    private int i = 100; 
    public synchronized void increment(){ i++; } 
    public synchronized int getVal(){ return i; } 
} 

現在,我認爲這應該給的120所希望的結果 - 但是結果似乎115和120之間波動。如果我添加一個Thread.sleep(1)b.start()我總是120的理想結果。爲什麼會發生這種情況?

它真的被迷惑了我,我想感謝所有幫助我能得到,謝​​謝

回答

3

您遇到後打印計數器的值開始所有線程,而不是在所有的線程都完成

在所有已開始等待完成的線程上使用Thread.join(),然後打印該值。或者使用CountDownLatch。睡覺給你正確的結果是意外的。它允許所有的線程完成,但僅僅是因爲它們有很少的事情要做,只需要1毫秒就足夠了。

+0

編輯戰爭以改善答案。伊馬讓你贏得加入/閂鎖......你打我:) – 2013-05-10 20:48:09

+0

這不是一場戰爭。只是想給出一個很好和完整的答案。 – 2013-05-10 20:49:59

+0

我的意思是我們都在不斷修改以增加更多細節,並不是說它必然是一場競賽,但它最終看起來就像它。 – 2013-05-10 20:50:30

1

因爲線程並行運行。

您正在主線程中打印c.getVal(),然後一個或多個其他線程將其遞增。

當你睡覺時,你讓其他線程有足夠的時間完成打印。

0

因爲到達System.out時並不是所有的線程都完成了它的增量任務。注入睡眠允許線程在完成輸出之前完成。

0

原因:

第三個線程(執行main())函數得到下面的語句以隨機順序啓動線程A和B之後,這就是爲什麼你會得到不可預知的結果。

System.out.println("The value of the balance is " + c.getVal()); 

下一個問題:

如果我添加了Thread.sleep(1)b.start()之後,我總是得到的120所希望的結果爲什麼會出現這種情況?

發生這種情況是因爲您停止主線程足夠長的時間(1秒鐘在CPU世界中很長時間)才允許線程a和b完成。

解決方案:使主線程等待,直到線程a和b都完成。方式一:

Counter c = new Counter(); 
    for (int i = 0; i < 10; i++) { 
     MyThread a = new MyThread(c); 
     MyThread b = new MyThread(c); 
     a.start(); 
     b.start(); 
    } 
    a.join(); // wait for thread a to finish 
    b.join(); // wait for thread b to finish 

    System.out.println("The value of the balance is " + c.getVal()); 
0

要打印的線程都完成可能之前(這就是爲什麼結果會發生變化)的結果。您需要等待,直到所有線程完成打印結果。

調整你main方法如下:

public static void main(String args[]) { 
    Counter c = new Counter(); 
    MyThread[] a = MyThread[20]; 
    for (int i = 0; i < 20; i++) { 
     a[i] = new MyThread(c); 
     a[i].start(); 
    } 
    for (int i = 0; i < 20; i++) { 
     a[i].join();   
    } 
    System.out.println("The value of the balance is " + c.getVal()); 
} 

首先,我循環20次,因爲你的循環重複10次,同時創建兩個線程(所以你創建20個線程太)。您需要堅持引用(通過a數組),以便主線程可以等待所有線程完成(使用join)。當他們全部完成後,返回正確的結果。