這篇文章主要為大家詳細介紹了Java concurrency之鎖的相關資料,具有一定的參考價值,有興趣的小伙伴們可以參考一下
根據鎖的添加到Java中的時間,Java中的鎖,可以分為"同步鎖"和"JUC包中的鎖"。
同步鎖定
即透過synchronized關鍵字來進行同步,實現對競爭資源的互斥存取的鎖定。 Java 1.0版本中就已經支援同步鎖定了。
同步鎖定的原理是,對於每一個物件,有且僅有一個同步鎖定;不同的執行緒能共同存取該同步鎖定。但是,在同一個時間點,該同步鎖能且只能被一個執行緒取得到。這樣,取得到同步鎖的執行緒就能進行CPU調度,從而在CPU上執行;而沒有取得到同步鎖的線程,必須進行等待,直到取得同步鎖之後才能繼續運作。這就是,多執行緒透過同步鎖進行同步的原理!
JUC套件中的鎖
# 相比同步鎖,JUC套件中的鎖的功能更加強大,它為鎖定提供了一個框架,這個框架允許更靈活地使用鎖,只是它的用法更難罷了。
JUC包中的鎖,包括:Lock接口,ReadWriteLock接口,LockSupport阻塞原語,Condition條件,AbstractOwnableSynchronizer/AbstractQueuedSynchronizer/AbstractQueuedLongSynchronizer三個抽像類,ReentrantLock獨佔鎖,ReentrantReadWriteLock讀寫鎖。由於CountDownLatch,CyclicBarrier和Semaphore也是透過AQS來實現的;因此,我也將它們歸納到鎖的框架中進行介紹。
先看看鎖的框架圖,如下圖。
01. Lock介面
JUC套件中的Lock 介面支援那些語意不同(重入、公平等)的鎖規則。所謂語意不同,是指鎖可是有"公平機制的鎖"、"非公平機制的鎖"、"可重入的鎖"等等。 "公平機制"是指"不同執行緒取得鎖的機制是公平的",而"非公平機制"則是指"不同執行緒取得鎖的機制是非公平的","可重入的鎖"是指同一個鎖能夠被一個執行緒多次取得。
02. ReadWriteLock
ReadWriteLock 介面以和Lock類似的方式定義了一些讀取者可以共享而寫入者獨佔的鎖。 JUC套件只有一個類別實作了該接口,即 ReentrantReadWriteLock,因為它適用於大部分的標準用法上下文。但程式設計師可以創建自己的、適用於非標準要求的實作。
03. AbstractOwnableSynchronizer/AbstractQueuedSynchronizer/AbstractQueuedLongSynchronizer
AbstractQueuedSynAQ
AbstractQueuedSynAQ
##[]SynAQ非常有用的超類,可用來定義鎖以及依賴於排隊阻塞執行緒的其他同步器;ReentrantLock,ReentrantReadWriteLock,CountDownLatch,CyclicBarrier和Semaphore等這些類別都是基於AQS類別實現的。 AbstractQueuedLongSynchronizer 類別提供相同的功能但擴展了對同步狀態的 64 位元的支援。兩者都擴展了類別 AbstractOwnableSynchronizer(一個幫助記錄當前保持獨佔同步的線程的簡單類別)。
# LockSupport提供「建立鎖定」和「其他同步類別的基本執行緒阻塞原語」。
LockSupport的功能和"Thread中的Thread.suspend()和Thread.resume()有點類似",LockSupport中的park() 和unpark() 的作用分別是阻塞線程和解除阻塞線程。但park()和unpark()不會遇到「Thread.suspend 和 Thread.resume可能引發的死鎖」問題。
Condition需要和Lock聯合使用,它的作用是取代Object監視器方法,可以透過await(),signal()來休眠/喚醒執行緒。
Condition 介面描述了可能會與鎖有關聯的條件變數。這些變數在用法上與使用 Object.wait 存取的隱式監視器類似,但提供了更強大的功能。需要特別指出的是,單一 Lock 可能與多個 Condition 物件關聯。為了避免相容性問題,Condition 方法的名稱與對應的 Object 版本中的不同。
06. ReentrantLock
# ReentrantLock是獨佔鎖定。所謂獨佔鎖,是指只能被獨自佔領,也就是同一個時間點只能被一個線程鎖獲取到的鎖。 ReentrantLock鎖包括"公平的ReentrantLock"和"非公平的ReentrantLock"。 "公平的ReentrantLock"是指"不同線程獲取鎖的機制是公平的",而"非公平的ReentrantLock"則是指"不同線程獲取鎖的機制是非公平的",ReentrantLock是"可重入的鎖" 。
ReentrantLock的UML類別圖如下:
(01) ReentrantLock實作了Lock介面。
(02) ReentrantLock中有一個成員變數sync,sync是Sync型別;Sync是一個抽象類,而且它繼承於AQS。
(03) ReentrantLock中有"公平鎖類別"FairSync和"非公平鎖類別"NonfairSync,它們都是Sync的子類別。 ReentrantReadWriteLock中sync對象,是FairSync與NonfairSync中的一種,這也意味著ReentrantLock是"公平鎖"或"非公平鎖"中的一種,ReentrantLock預設是非公平鎖。
07. ReentrantReadWriteLock
ReentrantReadWriteLock是讀寫鎖定介面ReadWriteLock的實作類,它包括子類ReadLock和WriteLock。 ReentrantLock是共享鎖,而WriteLock是獨佔鎖。
ReentrantReadWriteLock的UML類別圖如下:
(02) ReentrantReadWriteLock包含sync對象,讀鎖readerLock和寫鎖writerLock。讀鎖ReadLock和寫鎖WriteLock都實作了Lock介面。
(03) 和"ReentrantLock"一樣,sync是Sync型別;而且,Sync也是繼承給AQS的抽象類別。 Sync還包括"公平鎖"FairSync和"非公平鎖"NonfairSync。
08. CountDownLatch
CountDownLatch的UML類別圖如下:
09. CyclicBarrier
## CyclicBarrier是包含了"ReentrantLock物件lock"和"Condition物件trip",它是透過獨佔鎖實現的。
(01) CountDownLatch的作用是允許1或N個執行緒等待其他執行緒完成執行;而CyclicBarrier則是允許N個執行緒互相等待。
(02) CountDownLatch的計數器無法被重置;CyclicBarrier的計數器可以被重置後使用,因此它被稱為是循環的barrier。
10. Semaphore
Semaphore是一個計數訊號量,它的本質是一個"共享鎖定"。
信號量維護了一個信號量許可集。線程可以透過呼叫acquire()來取得信號量的許可;當信號量中有可用的許可時,線程能取得該許可;否則線程必須等待,直到有可用的許可為止。 線程可以透過release()來釋放它所持有的信號量許可。
Semaphore的UML類別圖如下:
和"ReentrantLock"一樣,Semaphore包含了sync對象,sync是Sync型別;而且,Sync也是一個繼承於AQS的抽象類別。 Sync還包括"公平信號量"FairSync和"非公平信號量"NonfairSync。
以上是Java中的鎖--同步鎖與JUC包中的鎖的詳細內容。更多資訊請關注PHP中文網其他相關文章!