1.object.wait()
使用方法:
線程A:
synchronized(obj){
obj.wait(); //此時當(dāng)前線程釋放obj鎖,進(jìn)入[等待狀態(tài)],等待其他線程執(zhí)行obj.notify()時才有可能執(zhí)行(有可能執(zhí)行的意思可能有多個線程執(zhí)行了wait)
A do something
}
線程C:
synchronized(obj){
obj.wait(); //此時當(dāng)前線程釋放obj鎖,進(jìn)入[等待狀態(tài)],等待其他線程執(zhí)行obj.notify()時才有可能執(zhí)行(有可能執(zhí)行的意思可能有多個線程執(zhí)行了wait)
C do something
}
線程B:
synchronized(obj){
obj.notify(); //此時當(dāng)前線程釋放obj鎖,隨機(jī)喚醒一個處于等待狀態(tài)的線程,繼續(xù)執(zhí)行wait后面的程序。
}
假設(shè)三個線程執(zhí)行順序
線程A-->線程C-->線程B //沒毛病,因?yàn)閣ait后是釋放了鎖的
所以問題來了:等待的線程中有A和C, B notify后,只會喚醒其中一個執(zhí)行(notifyAll同樣只有一個執(zhí)行);假如我們的需求是想讓A線程執(zhí)行,那么這種object的方式是無法控制的
2.所以condition來了
使用方法:注意condition是依賴ReentrantLock
ReentrantLock lock = new ReentrantLock(true);
Condition aCondition = reentrantLock.newCondition();
Condition cCondition = reentrantLock.newCondition();
線程A:
{
lock.lock();
aCondition.await(); //此時當(dāng)前線程釋放lock鎖,進(jìn)入[等待狀態(tài)],等待其他線程執(zhí)行aCondition.signal()時才有可能執(zhí)行
A do something
lock.unlock();
}
線程C:
{
lock.lock();
cCondition.await();
do something
lock.unlock();
}
線程B:
{
lock.lock();
aCondition.signal(); //此時當(dāng)前線程釋放lock鎖,隨機(jī)喚醒一個處于等待狀態(tài)等待aCondition的線程,繼續(xù)執(zhí)行await后面的程序。
//cCondition.signal(); ////此時當(dāng)前線程釋放lock鎖,隨機(jī)喚醒一個處于等待狀態(tài)等待cCondition的線程,繼續(xù)執(zhí)行await后面的程序。
lock.unlock();
}
所以通過condition與object進(jìn)行線程通信的區(qū)別已經(jīng)很明顯了,condition更加靈活。
個人理解,本質(zhì)上來講:
多線程環(huán)境的下,線程直接的互斥[執(zhí)行]依靠的應(yīng)該是鎖Lock,線程的之間的[通信]依靠的應(yīng)該是條件Condition/信號,一般情況下lock確實(shí)可以同時滿足做這兩個事情,所以在Object的方式滿足了這個一般情況,但是肯定會有復(fù)雜的場景比如剛才例子中,需要讓滿足一定條件的線程執(zhí)行,僅僅依靠鎖是不能完美解決的。所以condition實(shí)際上分離了執(zhí)行和通信。
以上僅是condition與object在應(yīng)用層面的上的區(qū)別,而背后的實(shí)現(xiàn)原理也是大有不同,以后再追加。