本章,我們介紹鎖的架構;后面的章節將會對它們逐個進行分析介紹。目錄如下:
01. Java多線程系列--“JUC鎖”01之 框架
02. Java多線程系列--“JUC鎖”02之 互斥鎖ReentrantLock
03. Java多線程系列--“JUC鎖”03之 公平鎖(一)
04. Java多線程系列--“JUC鎖”04之 公平鎖(二)
05. Java多線程系列--“JUC鎖”05之 非公平鎖
06. Java多線程系列--“JUC鎖”06之 Condition條件
07. Java多線程系列--“JUC鎖”07之 LockSupport
08. Java多線程系列--“JUC鎖”08之 共享鎖和ReentrantReadWriteLock
09. Java多線程系列--“JUC鎖”09之 CountDownLatch原理和示例
10. Java多線程系列--“JUC鎖”10之 CyclicBarrier原理和示例
11. Java多線程系列--“JUC鎖”11之 Semaphore信號量的原理和示例
根據鎖的添加到Java中的時間,Java中的鎖,可以分為"同步鎖"和"JUC包中的鎖"。
同步鎖
即通過synchronized關鍵字來進行(xing)同步(bu),實現對競爭資源的互(hu)斥訪問(wen)的鎖。Java 1.0版本中(zhong)就(jiu)已經支持(chi)同步(bu)鎖了。
同(tong)(tong)(tong)(tong)步(bu)(bu)鎖的(de)(de)原(yuan)理是(shi),對于每(mei)一(yi)(yi)(yi)個對象,有(you)且僅有(you)一(yi)(yi)(yi)個同(tong)(tong)(tong)(tong)步(bu)(bu)鎖;不同(tong)(tong)(tong)(tong)的(de)(de)線(xian)程能(neng)共同(tong)(tong)(tong)(tong)訪問該同(tong)(tong)(tong)(tong)步(bu)(bu)鎖。但是(shi),在同(tong)(tong)(tong)(tong)一(yi)(yi)(yi)個時間點,該同(tong)(tong)(tong)(tong)步(bu)(bu)鎖能(neng)且只能(neng)被一(yi)(yi)(yi)個線(xian)程獲取到(dao)。這樣(yang),獲取到(dao)同(tong)(tong)(tong)(tong)步(bu)(bu)鎖的(de)(de)線(xian)程就能(neng)進(jin)行(xing)(xing)CPU調度(du),從而(er)在CPU上執行(xing)(xing);而(er)沒有(you)獲取到(dao)同(tong)(tong)(tong)(tong)步(bu)(bu)鎖的(de)(de)線(xian)程,必須進(jin)行(xing)(xing)等(deng)待,直(zhi)到(dao)獲取到(dao)同(tong)(tong)(tong)(tong)步(bu)(bu)鎖之(zhi)后(hou)才(cai)能(neng)繼續運(yun)行(xing)(xing)。這就是(shi),多線(xian)程通過同(tong)(tong)(tong)(tong)步(bu)(bu)鎖進(jin)行(xing)(xing)同(tong)(tong)(tong)(tong)步(bu)(bu)的(de)(de)原(yuan)理!
關于"同步鎖"的更多內容,請參考"Java鎖的基礎部分"的內容。
JUC包中的鎖
相比同步(bu)鎖,JUC包中的鎖的功能(neng)更加強大,它為(wei)鎖提供(gong)了一(yi)個框架,該框架允許(xu)更靈活地使(shi)用鎖,只是(shi)它的用法更難罷了。
JUC包中的鎖,包括:Lock接口,ReadWriteLock接口,LockSupport阻塞原語(yu),Condition條件,AbstractOwnableSynchronizer/AbstractQueuedSynchronizer/AbstractQueuedLongSynchronizer三個抽(chou)象類(lei),ReentrantLock獨占鎖,ReentrantReadWriteLock讀寫鎖。由于CountDownLatch,CyclicBarrier和Semaphore也是通過AQS來實現的;因此,我也將它們歸納到鎖的框架中進行介紹(shao)。
先看(kan)(kan)看(kan)(kan)鎖的(de)框架圖,如下(xia)所示。
01. Lock接口
JUC包中(zhong)的(de) Lock 接口支持(chi)那(nei)些語義(yi)不(bu)同(tong)(重入(ru)(ru)、公(gong)(gong)平(ping)等)的(de)鎖規則(ze)(ze)。所謂語義(yi)不(bu)同(tong),是指(zhi)鎖可是有(you)"公(gong)(gong)平(ping)機(ji)(ji)制(zhi)(zhi)(zhi)的(de)鎖"、"非公(gong)(gong)平(ping)機(ji)(ji)制(zhi)(zhi)(zhi)的(de)鎖"、"可重入(ru)(ru)的(de)鎖"等等。"公(gong)(gong)平(ping)機(ji)(ji)制(zhi)(zhi)(zhi)"是指(zhi)"不(bu)同(tong)線程獲取鎖的(de)機(ji)(ji)制(zhi)(zhi)(zhi)是公(gong)(gong)平(ping)的(de)",而"非公(gong)(gong)平(ping)機(ji)(ji)制(zhi)(zhi)(zhi)"則(ze)(ze)是指(zhi)"不(bu)同(tong)線程獲取鎖的(de)機(ji)(ji)制(zhi)(zhi)(zhi)是非公(gong)(gong)平(ping)的(de)","可重入(ru)(ru)的(de)鎖"是指(zhi)同(tong)一(yi)個鎖能夠被(bei)一(yi)個線程多次獲取。
02. ReadWriteLock
ReadWriteLock 接口以(yi)和Lock類似的方式(shi)定(ding)義了一些讀(du)取者(zhe)可(ke)以(yi)共享(xiang)而寫入(ru)者(zhe)獨占(zhan)的鎖。JUC包只有(you)一個類實(shi)現(xian)了該接口,即 ReentrantReadWriteLock,因為它適用(yong)于大部(bu)分的標準用(yong)法上下文。但(dan)程(cheng)序員可(ke)以(yi)創(chuang)建(jian)自己(ji)的、適用(yong)于非(fei)標準要(yao)求(qiu)的實(shi)現(xian)。
03. AbstractOwnableSynchronizer/AbstractQueuedSynchronizer/AbstractQueuedLongSynchronizer
AbstractQueuedSynchronizer就是被稱之為AQS的類,它是一個非常有用的超類,可用來定義鎖以及依賴于排隊阻塞線程的其他同步器;ReentrantLock,ReentrantReadWriteLock,CountDownLatch,CyclicBarrier和Semaphore等這些類都是基于AQS類實現的。AbstractQueuedLongSynchronizer 類提供相同的功能但擴展了對同步狀態的 64 位的支持。兩者都擴展了類 AbstractOwnableSynchronizer(一個幫助記錄當前保持獨占同步的線程的簡單類)。
04. LockSupport
LockSupport提(ti)供“創建鎖”和(he)“其他同步(bu)類的基(ji)本(ben)線程(cheng)阻塞原語”。
LockSupport的功能和"Thread中(zhong)的Thread.suspend()和Thread.resume()有點類似",LockSupport中(zhong)的park() 和 unpark() 的作用分別是阻(zu)塞線程和解除(chu)阻(zu)塞線程。但是park()和unpark()不會(hui)遇到“Thread.suspend 和 Thread.resume所可能引(yin)發的死鎖”問題。
05. Condition
Condition需要和Lock聯合(he)使用,它的作用是代替Object監(jian)視器方法(fa),可(ke)以通過await(),signal()來休眠/喚醒線程。
Condition 接口描述了可(ke)(ke)能會(hui)與(yu)鎖有關聯(lian)的(de)(de)(de)(de)條(tiao)件變量(liang)。這些變量(liang)在用(yong)法(fa)(fa)上與(yu)使(shi)用(yong) Object.wait 訪問的(de)(de)(de)(de)隱式(shi)監視器(qi)類似,但(dan)提供了更強大的(de)(de)(de)(de)功能。需要特別指出的(de)(de)(de)(de)是,單(dan)個 Lock 可(ke)(ke)能與(yu)多個 Condition 對象關聯(lian)。為了避(bi)免(mian)兼容性問題(ti),Condition 方法(fa)(fa)的(de)(de)(de)(de)名稱與(yu)對應的(de)(de)(de)(de) Object 版本中的(de)(de)(de)(de)不同(tong)。
06. ReentrantLock
ReentrantLock是(shi)(shi)獨(du)占鎖(suo)(suo)(suo)。所謂獨(du)占鎖(suo)(suo)(suo),是(shi)(shi)指只(zhi)(zhi)能被(bei)獨(du)自(zi)占領,即同(tong)(tong)一個(ge)時(shi)間點只(zhi)(zhi)能被(bei)一個(ge)線(xian)(xian)程鎖(suo)(suo)(suo)獲取到的(de)鎖(suo)(suo)(suo)。ReentrantLock鎖(suo)(suo)(suo)包括"公(gong)平(ping)的(de)ReentrantLock"和"非(fei)公(gong)平(ping)的(de)ReentrantLock"。"公(gong)平(ping)的(de)ReentrantLock"是(shi)(shi)指"不(bu)同(tong)(tong)線(xian)(xian)程獲取鎖(suo)(suo)(suo)的(de)機制是(shi)(shi)公(gong)平(ping)的(de)",而"非(fei)公(gong)平(ping)的(de) ReentrantLock"則是(shi)(shi)指"不(bu)同(tong)(tong)線(xian)(xian)程獲取鎖(suo)(suo)(suo)的(de)機制是(shi)(shi)非(fei)公(gong)平(ping)的(de)",ReentrantLock是(shi)(shi)"可重入的(de)鎖(suo)(suo)(suo)"。
ReentrantLock的UML類圖如(ru)下:
(01) ReentrantLock實現了Lock接口。
(02) ReentrantLock中有一個(ge)成員變量sync,sync是Sync類型;Sync是一個(ge)抽(chou)象類,而且(qie)它繼承于(yu)AQS。
(03) ReentrantLock中有"公平(ping)鎖類"FairSync和(he)"非(fei)公平(ping)鎖類"NonfairSync,它們(men)都是(shi)Sync的子類。ReentrantReadWriteLock中sync對(dui)象,是(shi)FairSync與NonfairSync中的一種(zhong),這也意味著(zhu)ReentrantLock是(shi)"公平(ping)鎖"或"非(fei)公平(ping)鎖"中的一種(zhong),ReentrantLock默(mo)認是(shi)非(fei)公平(ping)鎖。
07. ReentrantReadWriteLock
ReentrantReadWriteLock是(shi)讀(du)寫鎖接(jie)口ReadWriteLock的實現類,它包括子(zi)類ReadLock和WriteLock。ReentrantLock是(shi)共享鎖,而WriteLock是(shi)獨占(zhan)鎖。
ReentrantReadWriteLock的UML類圖如下:

(01) ReentrantReadWriteLock實現了ReadWriteLock接口。
(02) ReentrantReadWriteLock中包含sync對象,讀鎖(suo)readerLock和(he)寫(xie)鎖(suo)writerLock。讀鎖(suo)ReadLock和(he)寫(xie)鎖(suo)WriteLock都實現了(le)Lock接口。
(03) 和"ReentrantLock"一樣,sync是(shi)Sync類(lei)型;而且(qie),Sync也是(shi)一個繼承(cheng)于AQS的(de)抽象類(lei)。Sync也包括"公(gong)平鎖"FairSync和"非公(gong)平鎖"NonfairSync。
08. CountDownLatch
CountDownLatch是一(yi)(yi)個同步輔助類,在(zai)完成一(yi)(yi)組正(zheng)在(zai)其他線程(cheng)中執行的操作之(zhi)前,它允許一(yi)(yi)個或(huo)多個線程(cheng)一(yi)(yi)直(zhi)等待。
CountDownLatch的UML類圖如(ru)下:

CountDownLatch包含了sync對象,sync是Sync類型。CountDownLatch的(de)Sync是實例類,它繼承于AQS。
09. CyclicBarrier
CyclicBarrier是(shi)一(yi)(yi)個同步輔助(zhu)類,允許(xu)一(yi)(yi)組線(xian)程(cheng)互(hu)相等(deng)待,直到(dao)到(dao)達(da)某(mou)個公共屏障點 (common barrier point)。因(yin)為該 barrier 在釋放(fang)等(deng)待線(xian)程(cheng)后(hou)可以(yi)重(zhong)用,所以(yi)稱(cheng)它(ta)為循(xun)環 的 barrier。
CyclicBarrier的UML類(lei)圖如下:

CyclicBarrier是包含了(le)"ReentrantLock對象lock"和"Condition對象trip",它(ta)是通過獨占鎖實現的。
CyclicBarrier和CountDownLatch的區(qu)別是:
(01) CountDownLatch的作用是(shi)(shi)允許1或N個(ge)線程等(deng)待其他線程完(wan)成執行;而(er)CyclicBarrier則是(shi)(shi)允許N個(ge)線程相互等(deng)待。
(02) CountDownLatch的(de)(de)計數器(qi)無法(fa)被重置(zhi);CyclicBarrier的(de)(de)計數器(qi)可以被重置(zhi)后使用,因此它被稱為是循環的(de)(de)barrier。
10. Semaphore
Semaphore是一個計數信號(hao)量,它的(de)本(ben)質是一個"共享(xiang)鎖"。
信(xin)號(hao)量(liang)維護了(le)一個信(xin)號(hao)量(liang)許(xu)(xu)可(ke)(ke)集。線(xian)程(cheng)(cheng)可(ke)(ke)以(yi)通過(guo)(guo)調(diao)用(yong)(yong)acquire()來獲取(qu)信(xin)號(hao)量(liang)的(de)許(xu)(xu)可(ke)(ke);當(dang)信(xin)號(hao)量(liang)中有可(ke)(ke)用(yong)(yong)的(de)許(xu)(xu)可(ke)(ke)時,線(xian)程(cheng)(cheng)能獲取(qu)該許(xu)(xu)可(ke)(ke);否則線(xian)程(cheng)(cheng)必須等待(dai),直到(dao)有可(ke)(ke)用(yong)(yong)的(de)許(xu)(xu)可(ke)(ke)為止。 線(xian)程(cheng)(cheng)可(ke)(ke)以(yi)通過(guo)(guo)release()來釋放它所持有的(de)信(xin)號(hao)量(liang)許(xu)(xu)可(ke)(ke)。
Semaphore的UML類(lei)圖如下:

和(he)"ReentrantLock"一樣,Semaphore包含了sync對(dui)象,sync是Sync類型;而且,Sync也是一個繼承于AQS的抽象類。Sync也包括(kuo)"公平信(xin)號量"FairSync和(he)"非公平信(xin)號量"NonfairSync。


