1. 程式人生 > >多執行緒synchronized, wait, notify, sleep 理解

多執行緒synchronized, wait, notify, sleep 理解

最近在看多執行緒,參考了一篇 部落格 ,覺得寫得比較好,但是在一段相關物件鎖的程式碼上卡住了,理解不了,問了同學,加上自己的理解,終於搞懂了。

測試程式碼
package com.fehead.test;
import com.fehead.thread.MyThreadPrinter;

public class Test {

	public static void main(String[] args) throws Exception {
		Object a = new Object();
		Object b = new Object();
		Object c =
new Object(); MyThreadPrinter pa = new MyThreadPrinter("A", c, a); MyThreadPrinter pb = new MyThreadPrinter("B", a, b); MyThreadPrinter pc = new MyThreadPrinter("C", b, c); new Thread(pa).start(); Thread.sleep(100); new Thread(pb).start(); Thread.sleep(100); new Thread(pc).start(); Thread.
sleep(100); } }
package com.fehead.thread;

public class MyThreadPrinter implements Runnable {
	private String name;
	private Object prev;
	private Object self;
	
	public MyThreadPrinter(String name, Object prev, Object self) {
		this.name = name;
		this.prev = prev;
		this.self = self;
	}
	
	@Override
public void run() { int count = 10; while(count > 0) { synchronized (prev) { synchronized (self) { System.out.print(name); count--; self.notify(); } try { prev.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } } } }
輸出結果
  • ABCABCABCABCABCABCABCABCABCABC
個人理解
  • sleep() 開始,Thread.sleep(100);能讓執行緒暫停100ms,可以看到執行緒pa沒有執行緒休眠,執行緒pb休眠了100ms,而執行緒pc休眠了200ms(至於第三個Thread.sleep(100);有什麼作用我還沒搞懂,歡迎大神留言解惑)。

  • 物件鎖,顧名思義,實際上是一把鎖,wait()是鎖,而prev,self(物件a,b,c)是鎖孔的形狀,相對的notify()是鑰匙,與之對應的prev,self(物件a,b,c)是鑰匙的形狀。

  • 回到程式碼

    1. 首先開始的是pa同學,他先拿起了c鎖,然後又拿起了a鎖,用鑰匙打開了a鎖(雖然a鎖並沒有鎖住任何東西···),接著放下了a鎖,用c鎖把自己鎖住了,最後放下了c鎖;
    2. 接下來是pb同學,他一上來就要拿a鎖,(但是pa比他快了一步,所以他只能等pa放下a鎖後再拿a1), 接著他有拿到了b鎖,用鑰匙打開了b鎖(雖然b鎖也沒有鎖住任何東西···),接著放下了b鎖,用a鎖把自己鎖住了,最後放下了a鎖;
    3. 最後是pc同學,他先拿起了b鎖,然後又拿起了c鎖,用鑰匙打開了c鎖,還記的用c鎖把自己鎖起來的pa吧,這個時候他就被放了出來,所以他又開始行動了,接著pc放下了c鎖,用b鎖把自己鎖住了,最後放下了b鎖;
    4. 話說papc放出來了,他又拿起了c鎖,然後又拿起了a鎖,用鑰匙打開了a鎖(a鎖原本鎖住的pb被放了出來),接著放下了a鎖,用c鎖把自己鎖住了,最後放下了c鎖;
    5. 話說pbpa放出來了,他又拿起了a鎖,然後又拿起了b鎖,用鑰匙打開了b鎖(b鎖原本鎖住的pc被放了出來),接著放下了b鎖,用a鎖把自己鎖住了,最後放下了a鎖;
    6. ······
    7. 如此往復,因為while()迴圈了10次,因此順序輸出ABC10次。
  • 圖片理解
    模型理解

理解錯誤

我在理解物件鎖的時候有過一個錯誤,認為每一個物件鎖對應一個執行緒,a對應pab對應pbc對應pc,實際上wait()是使本執行緒休眠,也就是不管是哪個物件鎖,執行wait()鎖住的一定是本執行緒。


因為是個人理解,所以不一定正確,如果有錯誤,歡迎大佬指正。


  1. 這句話是為了說明不同的執行緒不能同時呼叫同一個物件鎖 ↩︎