2016-09-15 41 views
-4
public class Test implements Runnable{ 
    private String name; 

    public Test(String name){ 
     this.name = name; 
    } 

    public void run() { 
     blah(name); 
    } 

    public synchronized void blah(String obj) { 
     System.out.println("Here: "+obj); 
     try { 
      Thread.sleep(10000); 
     } catch (InterruptedException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } 
    } 
} 

public static void main(String[] args) { 

    Test x = new Test("X"); 
    Test y = new Test("Y"); 

    Thread tx = new Thread(x); 
    Thread ty = new Thread(y); 

    tx.start(); 
    ty.start(); 

} 

這個例子應該有助於我理解同步,但我不這樣做。這是因爲如果我刪除單詞synchronize,它會打印相同的輸出(隨機)需要一個簡單的例子來實現同步

+0

[看看這個更好的例子](http://www.tutorialspoint.com/java/java_thread_synchronization.htm) – Draken

+0

「這個例子應該有助於我理解同步,但我不知道。」我們可以知道你從哪裏得到這個例子? – Pshemo

回答

0

您的示例在技術上是正確的,但在同步塊中沒有與時間有關的衝突。因此,無論呼叫的順序如何,您都不會看到不同的輸出。

另外,您創建了兩個資源,並且兩個資源之間沒有跨線程通信,所以有效地測試了兩個同步塊。

您需要一個在未同步時可以中斷的示例。

這裏是一個可以打破

public class Counter { 

    int count; 

    public Counter() { 
     count = 0; 
    } 


    public int getCount() { 
     return count; 
    } 

    public /* need synchronized here */ void update(int value) { 
     int buffer = 0; 
     buffer = buffer + count; 
     buffer = buffer + value; 
     count = buffer; 
    } 

} 

public class UpdateCounter extends Thread { 

    public UpdateCounter(Counter counter, int amount) { 
     this.counter = counter; 
     this.name = name; 
    } 

    public void run() { 
     System.out.printf("Adding %d to count\n", amount); 
     counter.update(amount); 
     System.out.printf("Count is %d\n", counter.getCount()); 
    } 
} 

public static void main(String[] args) { 
    Counter counter = new Counter(); 

    UpdateCounter x = new UpdateCounter(counter, 30); 
    UpdateCounter y = new UpdateCounter(counter, 100); 

    x.start(); 
    y.start(); 

} 

像這樣的例子爲例,一個最終會看到一系列指示正在將計數器一些價值線,但計數器會被更新錯誤的價值。

這是因爲一個線程最終會在緩衝區中保持「下一個」值而暫停,另一個線程將在同一代碼塊中競爭,並將其「下一個」值存儲到計數中。然後,暫停的線程將會暫停,並將其「下一個」值存儲起來,以便有效地移除在其之前的線程添加的數量。

通過添加synchronized關鍵字,只允許一個線程進入更新塊,並且上述競態條件不會發生。

請注意,這是一個可能因錯誤同步而失敗的示例,並且不是實現計數器的好方法。

2

同步在這裏是無關緊要的,因爲你的兩個線程每個在它們自己的Runnable上同步。沒有共享鎖,也沒有共享數據。

如果您將相同的Runnable實例傳遞給每個線程,那麼它們將共享相同的鎖。如果Runnable以線程不安全的方式執行某些操作(例如使用++來增加共享變量(Runnable的實例變量)或將該條目添加到共享ArrayList中),那麼您可以創建一種情況,即刪除同步可以使代碼中斷(瞭解破壞可能不會可靠發生,這就是多線程編程的樂趣所在)。

製作玩具這樣的例子對現實生活中的多線程並不是一個好的準備。線程不應該在實現鎖定的業務中,他們應該訪問強制自己的不變量的數據對象。

相關問題