多執行緒synchronized, wait, notify, sleep 理解
阿新 • • 發佈:2018-11-26
最近在看多執行緒,參考了一篇 部落格 ,覺得寫得比較好,但是在一段相關物件鎖的程式碼上卡住了,理解不了,問了同學,加上自己的理解,終於搞懂了。
測試程式碼
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)是鑰匙的形狀。 -
回到程式碼
- 首先開始的是
pa
同學,他先拿起了c
鎖,然後又拿起了a
鎖,用鑰匙打開了a
鎖(雖然a
鎖並沒有鎖住任何東西···),接著放下了a
鎖,用c
鎖把自己鎖住了,最後放下了c
鎖; - 接下來是
pb
同學,他一上來就要拿a
鎖,(但是pa
比他快了一步,所以他只能等pa
放下a
鎖後再拿a
鎖 1), 接著他有拿到了b
鎖,用鑰匙打開了b
鎖(雖然b
鎖也沒有鎖住任何東西···),接著放下了b
鎖,用a
鎖把自己鎖住了,最後放下了a
鎖; - 最後是
pc
同學,他先拿起了b
鎖,然後又拿起了c
鎖,用鑰匙打開了c
鎖,還記的用c
鎖把自己鎖起來的pa
吧,這個時候他就被放了出來,所以他又開始行動了,接著pc
放下了c
鎖,用b
鎖把自己鎖住了,最後放下了b
鎖; - 話說
pa
被pc
放出來了,他又拿起了c
鎖,然後又拿起了a
鎖,用鑰匙打開了a
鎖(a
鎖原本鎖住的pb
被放了出來),接著放下了a
鎖,用c
鎖把自己鎖住了,最後放下了c
鎖; - 話說
pb
被pa
放出來了,他又拿起了a
鎖,然後又拿起了b
鎖,用鑰匙打開了b
鎖(b
鎖原本鎖住的pc
被放了出來),接著放下了b
鎖,用a
鎖把自己鎖住了,最後放下了a
鎖; - ······
- 如此往復,因為
while()
迴圈了10次,因此順序輸出ABC10次。
- 首先開始的是
-
圖片理解
理解錯誤
我在理解物件鎖的時候有過一個錯誤,認為每一個物件鎖對應一個執行緒,a
對應pa
,b
對應pb
,c
對應pc
,實際上wait()
是使本執行緒休眠,也就是不管是哪個物件鎖,執行wait()
鎖住的一定是本執行緒。
因為是個人理解,所以不一定正確,如果有錯誤,歡迎大佬指正。
這句話是為了說明不同的執行緒不能同時呼叫同一個物件鎖 ↩︎