2012-11-27 61 views
0

好吧,假設我有一個具有線程安全實現的Java Math類。線程A現在正在執行SetValue(1),並導致Math類被鎖定。如果線程B嘗試同時訪問GetValue(),會發生什麼情況?它是否會等到鎖定釋放或方法請求直接終止而沒有警告或異常?當第一個線程鎖定類時第二個線程會發生什麼

public class Math { 
     private static int value = 0; 

     public synchronized static void setValue(int value) { 
      Math.value = value; 
     } 

     public synchronized static int getValue() { 
      return value; 
     } 
} 
+5

首先,您不能在靜態方法中使用「this」。 – Juvanis

+0

對不起,我只是用純粹的寫作做了個快速的例子。我想確保當類被鎖定時下一個線程的行爲。 – lannyboy

+0

這裏有幾點需要注意:1)從int分配/讀取是所有Java實現的原子操作,所以'synchronized'在這方面沒有幫助。 2)即使班級同步,它也不會阻止競賽狀況。 –

回答

1

如果第一個線程釋放鎖,它將永久等待(如有必要)。

+0

感謝您的答案:)然後,這是適用於我的單身線程安全的網頁設計:) – lannyboy

+0

是的。但爲什麼不使用AtomicInteger? –

+0

不,這不是我的原創設計,我只是爲了一個樣品而在原始類型中輸入。我只是想確保類鎖定時的下一個線程行爲。 – lannyboy

3

是的第二個線程將等待,直到鎖再次可用。如果鎖永遠不可用,您將遇到活躍問題,並且您的第二個線程將掛起。

它更詳細地描述在JLS 17.1

一個同步的方法自動地執行,當它被調用的鎖定動作;在鎖定動作成功完成之前,其主體不會執行。 [...]如果通常或突然執行方法主體的執行,則會在同一臺顯示器上自動執行解鎖操作。

還要注意:

Java編程語言既不阻止也不要求死鎖情況進行檢測。線程(直接或間接)鎖定多個對象的程序應該使用常規技術來避免死鎖,如有必要,創建不會死鎖的更高級鎖定原語。

1

Thread被加到等待隊列,它仍然有直到Thread A正在執行SetValue方法,並且不釋放該鎖。

只要Thread A解鎖,Thread B被通知,並且此後可以繼續。

另請注意,當Thread A進入SetValue方法時,它會獲取該類的所有同步方法的鎖定。因此,Thread B不能執行任何synchronized method,直到Thread A完成執行SetValue方法,並逐漸釋放鎖定。

還有一件事,一旦鎖被釋放,並不能保證Thread B會立即開始執行GetValue方法。這一切都取決於CPU,當它分配資源到線程B.


P.S: -請遵循Java命名約定在你的代碼。您的方法名稱應以lowercase開頭。所以,你的方法應該是getValuesetValue

+0

簡短,簡潔的答案。 +1。 – Juvanis

+0

感謝您的詳細解釋:) – lannyboy

+0

@lannyboy ..不客氣:) –

1

小插圖:

public class Math { 

private static int value = 0; 

public synchronized static void SetValue(int _value) throws InterruptedException { 

    Thread.sleep(1000L); 
    value = _value; 
} 

public synchronized static int GetValue() { 

    return value; 
} 

public static void main(String[] args) { 

    new Thread(new Runnable() { 

    @Override 
    public void run() { 

    try { 
    SetValue(-100); 
    } catch (InterruptedException e) { 
    // ignore 
    } 
    } 
    }).start(); 

    new Thread(new Runnable() { 

    @Override 
    public void run() { 

    System.out.println("GetValue() = " + GetValue()); 
    } 
    }).start(); 
} 
} 

輸出是:

GetValue() = -100 

這意味着,第二線程將要等待的第一個睡眠用於第二和設置之後醒來value100

+1

感謝您的解釋:) – lannyboy

相關問題