java.util.concurrent.locks.Lock文档说明
【1】Lock接口文檔描述
1.相比于使用synchronized方法和代碼塊,鎖的出現提供了更廣泛的鎖操作。
鎖允許更靈活的代碼結構,具有許多不同的屬性,還支持多個關聯的Condition條件對象。
2.鎖是用于控制多個線程訪問共享資源的工具。通常,鎖提供了對共享資源的獨占(排他)訪問,即某一時刻,只能有1個線程可以獲得鎖,所有對共享資源的訪問都必須事先獲得鎖。
然而,一些鎖允許對共享資源的并發訪問,如讀寫鎖 ReadWriteLock的讀鎖。
3.使用synchronized方法或代碼塊進行并發控制,實際是對每個對象的隱式監視器鎖(monitorenter+monitorexit)的訪問,且強制讓鎖的獲取與釋放發生在塊結構中。當獲取了多個鎖,這些鎖需要相反的順序釋放。而且所有鎖必須在它們被獲取時的作用域里釋放;
4.雖然 synchronized方法與代碼塊的作用域機制使得使用監視器鎖編碼更加容易,也有助于避免許多常見的涉及鎖的變成錯誤,但某些情況下,你需要以更加靈活的方式使用鎖。
如一些并發遍歷數據結構的算法需要使用 交叉(hand-over-hand)或鏈鎖(chain lock):你先獲取節點A的鎖,接著B,然后釋放A,獲取C,然后釋放B....等等。
還比如,使用可中斷方式,或非阻塞方式獲取鎖,或超時方式獲取鎖(超時前阻塞,超時后立即返回,無論獲取鎖與否),而不是像 synchronized那樣一直阻塞,不可中斷,沒有超時機制(非常死板)(干貨——為什么需要使用Lock而不是synchronized實現鎖);
Lock接口的實現允許在不同的作用域獲取和釋放鎖,并允許以任意順序獲取和釋放鎖。
Lock接口 與 synchronized 進行并發控制的最大區別小結:
5.這種增加的靈活性帶來了額外的責任。Lock接口沒有使用代碼塊結構,這樣消除了synchronized中的鎖自動釋放功能。
6.在大多數情況下,應該使用以下語句進行 Lock對象的鎖獲取與釋放;
Lock l = ...;l.lock();try {// access the resource protected by this lock} finally {l.unlock();}7.當鎖的獲取與釋放發生在不同作用域時,需要特別注意,讓持有鎖時執行的所有代碼都在 try-finally 或 try-catch 塊中受到保護,以確保必要時釋放鎖;
8.Lock的實現比synchronized多提供了其他方法(更加靈活,或者兩者的不同點),如
tryLock()方法-通過非阻塞方式嘗試獲取鎖; lockInterruptibly() 方法-嘗試獲取的鎖,獲取過程可被中斷; tryLock(long time, TimeUnit unit) -有超時限制的嘗試獲取鎖(超時后,立即返回,不會一直阻塞);9.Lock還提供了與隱式監視器鎖不同的行為和語義,如保證有序,非重入使用,死鎖檢測。如果鎖的實現提供了這樣專門的語義,則該實現必須記錄這些語義。
10.注意: Lock實例僅僅是普通對象,Lock對象本身可以作為synchronized語句的目標對象,如
synchronized(LockIntance){...}獲取Lock實例的監視器鎖與 調用Lock實例的lock方法沒有關系。墻裂建議不要在 synchronized語句塊中獲取Lock實例的監視器鎖,以避免混淆。
11.內存同步
所有Lock的實現都必須強制相同的內存同步語義(內存可見性),就像內建的監視器鎖一樣,據java語言規范所描述的那樣:成功的鎖定操作與成功的Lock動作有相同的內存同步效果,不成功的鎖定操作與不成功的UnLock動作有相同的內存同步效果。不成功的加鎖和解鎖操作,可重入加鎖和解鎖操作,不要求任何的內存同步效果;
12. Lock實現類注意事項
獲取Lock鎖的3種方式,包括可中斷,不可中斷,超時,在性能特征,順序保證,和其他方面都不相同。此外,在給定Lock類中,可能無法中斷獲取鎖的過程。因此,不需要為3種方式定義相同的保證與語義,也不需要支持對鎖獲取的中斷。鎖的實現需要清楚記錄每個鎖方法的語義和保證。Lock實現類也必須遵守如接口中定義的中斷語義,當需要支持鎖獲取的中斷的時候,完全或僅有一個方法入口。
13.中斷意味著取消,但中斷檢測不常發生,因此鎖的實現(Lock接口實現類)傾向于響應中斷而不是從方法返回。
即使證明了另一個動作之后發生的中斷會解除線程阻塞,也是如此。鎖的實現應該記錄這些行為。
【2】Lock方法描述
【2.1】void lock()
獲取鎖;如果鎖不可用(獲取鎖失敗),則當前線程將被線程調度器禁用,并休眠直到可以獲得鎖(當前線程阻塞);
Lock接口實現類注意事項:
Lock接口的實現類可能探測到鎖的錯誤使用,如死鎖,并在這種情況下拋出異常(未檢測異常)。Lock的實現必須記錄這種情況和異常類型。
【2.2】void lockInterruptibly() throws InterruptedException;
1.獲取鎖,除非當前線程中斷;
2.如果鎖可用,則獲取鎖并立即返回。
3.如果鎖不可用(獲取鎖失敗),則當前線程將被線程調度器禁用,并休眠直到出現以下兩種情況之一(當前線程阻塞)。
- 情況1,當前線程獲取鎖;
- 情況2,某個其他線程中斷了當前線程(當Lock實現類支持獲取鎖時的中斷);
4.如果當前線程:
在方法入口設置了中斷狀態,或者在獲取鎖時被中斷了,則會該線程拋出 中斷異常InterruptedException,且其中斷狀態被清除。
5.Lock實現類注意事項
在某些Lock接口的實現類中,中斷一個獲取鎖的線程是不可能的,如果可能,那也是非常昂貴的操作。程序員應該注意這種情況。Lock的實現也應該記錄這種情況。
6.與正常方法返回相比,Lock實現類更傾向于響應中斷;
7.Lock實現類可能探測到鎖的錯誤使用,如死鎖,并在這種情況下拋出異常(未檢測異常)。Lock的實現類必須記錄這種情況和異常類型。
8.拋出異常:
InterruptedException-可中斷異常,若當前線程在獲取鎖時被中斷了;
【2.3】boolean tryLock()
1.只要當前線程調用該方法時鎖是空閑的,則獲取鎖;
2.如果鎖可用,則獲取鎖并立即返回true;如果鎖不可用,則立即返回flase(當前線程不會阻塞);
3.典型用法如下:
Lock lock = ...;if (lock.tryLock()) {try {// 操作保護的狀態} finally {lock.unlock();}} else {// 執行替代操作 }這種用法確保了在獲取鎖時可以解鎖,在沒有獲取鎖時不會嘗試解鎖。
返回:若獲取鎖返回true,否則返回false;
【2.4】boolean tryLock(long time, TimeUnit unit) throws InterruptedException
1.如果鎖在給定等待時間內是空閑的且當前線程沒有被中斷,則當前線程獲取鎖;
2.若鎖可用,該方法立即返回true。若鎖不可用,則當前線程無法被調度器調度,且會阻塞直到發生以下3種情況之一(當前線程阻塞):
- 情況1, 當前線程獲取鎖;
- 情況2, 其他線程中斷當前線程(當Lock實現類支持鎖獲取時的中斷);
- 情況3,經過了給定等待時間,成功獲取了鎖則立即返回true;
3.如果當前線程:
在方法入口設置了中斷狀態,或者當前線程在獲取鎖時被中斷了(當Lock實現類支持獲取鎖時的中斷),則該線程拋出 中斷異常InterruptedException,且中斷狀態被清除。
4.與正常方法返回或報告超時相比,Lock實現類更傾向于響應中斷;
5.Lock接口的實現類可能探測到鎖的錯誤使用,如死鎖,并在這種情況下可能拋出異常(未檢測異常)。Lock的實現類必須記錄這種情況和異常類型。
6.參數列表:
- time, 等待鎖可用的最大時間;
- unit, time的時間單位,如時、分、秒
7.返回:
若獲取到鎖,返回true;若經過等待時間沒有獲取到鎖,返回false;
8.拋出異常:
InterruptedException-可中斷異常,若當前線程在獲取鎖時被中斷了(當Lock實現類可以支持獲取鎖時的中斷);
【2.5】void unlock() -釋放鎖。
1.Lock實現類的注意事項:
Lock實現類通常會對釋放鎖的線程施加限制(典型情況是只有鎖的持有者可以釋放鎖),且若違反限制,則可能拋出異常(unchecked)。
Lock實現類必須記錄任何限制和異常。
【2.6】Condition newCondition()
1.返回綁定到此Lock實例的新的Condition實例。
2.在等待condition之前,當前線程必須持有鎖。
3.調用Condition.await() 方法會在等待之前自動釋放鎖,并在等待返回之前重新獲取鎖;
4.Lock實現類注意事項
Condition實例的正確操作依賴于Lock的實現類。Lock實現類必須記錄這些操作。
5.返回:
該Lock實例的新的Condition實例;
6.拋出異常:
UnsupportedOperationException-不支持的操作異常-若鎖實現類不支持 condition;
【3】Lock方法總結
【3.1】Lock獲取鎖方法
| 方法 | 描述 | 當前線程 是否阻塞 |
| void lock() | 獲取鎖;如果鎖不可用(獲取鎖失敗),則當前線程將被線程調度器禁用,并休眠直到可以獲得鎖(當前線程阻塞); | 阻塞(不可中斷) |
| void lockInterruptibly() throws InterruptedException | 1.獲取鎖,除非當前線程中斷; | 阻塞 (但可中斷) |
| boolean tryLock() | 1.只要當前線程調用該方法時鎖是空閑的,則當前線程獲得鎖; 2.如果鎖可用,則獲取鎖并立即返回true;如果鎖不可用,則立即返回flase(當前線程不會阻塞) | 不阻塞 |
| boolean tryLock(long time, TimeUnit unit) throws InterruptedException | 1.如果鎖在給定等待時間內是空閑的且當前線程沒有被中斷,則當前線程獲取鎖; | 阻塞 (可中斷,且超時后立即返回,無論獲取鎖與否) |
【3.2】Lock其他方法
void unlock,釋放鎖;
Condition newCondition(), 獲取新的Condition實例;
總結
以上是生活随笔為你收集整理的java.util.concurrent.locks.Lock文档说明的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 寿比南山的南山指的是哪座山(寿比南山的南
- 下一篇: java.util.concurrent