接上篇:http://blog.csdn.net/wabiaozia/article/details/79429585
有個朋友看點擊開啟連結 裡的三個線程“A線程列印10次A,B線程列印10次B,C線程列印10次C,要求線程同時運行,交替列印10次ABC。” 這個問題的代碼,有點不太理解,讓我給看下。不理解的原因也很簡單,就是對wait和notify理解不深,遇到複雜點的情境會迷糊。對於並發相關的東西,非常推薦書並發編程實戰(童雲蘭譯)。這篇部落格純粹是為了直觀理解而寫,所以講解時用詞不準確,如果是想看一些概念的精確定義,建議看書,不要看這篇。
本文:
一些概念:
1 wait會釋放鎖,並使當前線程休眠。
2 有一點需要注意的是notify()調用後,並不是馬上就釋放對象鎖的,而是在相應的synchronized(){}語句塊執行結束,自動釋放鎖。
結合代碼理解:
問1: "wait會釋放鎖,並使當前線程休眠"的理解
第一次A線程先執行,new Thread(pa).start()。在代碼中1和2處分別擁有prev(c鎖)和self(a鎖)。對於初學者來說在A線程過程中,代碼中4處要理解到哪些點呢。
第一點,wait會釋放鎖,釋放誰的鎖。因為是prev.wait(),所以釋放的是prev鎖,即c鎖。第二點,使線程休眠,哪個線程休眠。是不是說因為是prev.wait(),所以休眠的是prev(c鎖)對應的c線程呢。不是,這裡的休眠是當前啟動並執行線程休眠,即A線程休眠,而不是c線程休眠。第三點,如何喚醒A線程呢,使用a.notify還是c.notify。是不是說當前線程休眠了,用當前線程喚醒(a.notify)就行了。不是,前面用的是c.wait (即代碼中的prev.wait,執行時參數prev代指的就是c)使線程A休眠。所以這裡仍然需要c.notify喚醒線程A。
問2: notify()調用後,會馬上就釋放對象鎖
下文中的代碼3處,notify()調用後並不是馬上就釋放對象鎖的,而是在相應的synchronized(){}語句塊執行結束,自動釋放鎖。
問3:小結下A線程的執行流程
執行代碼1和2處,分別是c和a鎖,這點很好理解。代碼3處釋放a鎖。代碼4處,釋放c鎖,同時休眠A線程,下次需要c.notify() 才能喚醒A線程。
問4:還有其他解法嗎。轉載表明連結:http://blog.csdn.net/wabiaozia/article/details/79534560
有lock鎖,ReentrantLock結合Condition,訊號量Semaphore等。我部落格所有文章連結:http://blog.csdn.net/wabiaozia
/** * wait用法 * @author DreamSea * @time 2015.3.9 */package com.multithread.wait;public class MyThreadPrinter2 implements Runnable { private String name; private Object prev; private Object self; private MyThreadPrinter2(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) { // 1 代碼1 處 synchronized (self) { // 2 代碼2 處 System.out.print(name); count--; self.notify(); // 3 代碼3處 } try { prev.wait(); // 4 代碼4處 } catch (InterruptedException e) { e.printStackTrace(); } } } } public static void main(String[] args) throws Exception { Object a = new Object(); Object b = new Object(); Object c = new Object(); MyThreadPrinter2 pa = new MyThreadPrinter2("A", c, a); MyThreadPrinter2 pb = new MyThreadPrinter2("B", a, b); MyThreadPrinter2 pc = new MyThreadPrinter2("C", b, c); new Thread(pa).start(); Thread.sleep(100); //確保按順序A、B、C執行 new Thread(pb).start(); Thread.sleep(100); new Thread(pc).start(); Thread.sleep(100); } }