1

我有一個方法shout()與一個同步塊。我是否對我的關於同步塊的假設正確?

private void shout(){ 
    System.out.println("SHOUT " + Thread.currentThread().getName()); 
    synchronized(this){ 
     System.out.println("Synchronized Shout" + Thread.currentThread().getName()); 
     try { 
     Thread.sleep(50); 
     } 
     catch (InterruptedException e) { 
     e.printStackTrace(); 
     } 
     System.out.println("Synchronized Shout" + Thread.currentThread().getName()); 
    } 
    } 

如果我有一個運行此方法兩個線程,是我糾正假設兩個「同步怒吼」總是會出現一個接一個? 「Synchronized Shout」之間不能有其他陳述?

回答

2

只要this參考是相同的。如果您在兩個不同的對象上運行代碼,鎖定將不起作用。

注意,如果你使用的thisObject.wait而不是調用Thread.sleep拖延,那麼鎖將被刪除(在移動之前重新獲取)。

2

由於打印「SHOUT ...」的行不需要鎖定,因此它可以出現在任何點上。因此,即使一個線程持有鎖,另一個線程可能會進入並打印「SHOUT ...」。

下面的代碼顯示的交織:

public class Interleave { 
    public static void main(String[] args) throws Throwable { 
    Task task = new Task(); 
    Thread t1 = new Thread(task); 
    Thread t2 = new Thread(task); 
    t1.start(); 
    Thread.sleep(25); 
    t2.start(); 
    } 

    private static class Task implements Runnable { 
    public void run() { 
     shout(); 
    } 

    private void shout() { 
     System.out.println("SHOUT " + Thread.currentThread().getName()); 
     synchronized (this) { 
     System.out.println("Synchronized Shout " + Thread.currentThread().getName()); 
     try { 
      Thread.sleep(50); 
     } catch (InterruptedException e) { 
      e.printStackTrace(); 
     } 
     System.out.println("Synchronized Shout " + Thread.currentThread().getName()); 
     } 
    } 
    } 
} 

它打印出

SHOUT Thread-0 
Synchronized Shout Thread-0 
SHOUT Thread-1 
Synchronized Shout Thread-0 
Synchronized Shout Thread-1 
Synchronized Shout Thread-1 
+0

然後我不明白同步塊的重點。 – unj2 2010-05-03 16:45:41

+0

@ kunjaan同步的確提供了「互斥」。但非常重要的一點是,互斥僅限於參與同一鎖定的線程。任何不參與相同鎖的線程的進度都不受影響。因此,執行不需要獲取相同鎖的代碼區域的任何線程(例如打印位於同步塊之外的「SHOUT ...」的行)根本不受鎖定的影響。同理,任何嘗試獲取不同對象鎖的線程也不會受到影響(Tom Hawtin指出)。 – sjlee 2010-05-03 16:52:51

0

當兩個或多個線程對同一實例中運行,然後呼喊可以出現在任何地方,因爲它的外同步塊,因此未被保護。 「同步發言」總是嚴格按照順序出現,沒有任何同步化呼喊來自另一個線程進入並影響命令。