引言
鎖,是java se 5之后提出的萄焦,它同synchronized關鍵字一樣不恭,都是用來控制多個線程對臨界區(qū)訪問的灵妨。
Lock與synchronized之間的區(qū)別和聯(lián)系
在總結(jié)兩者的區(qū)別和聯(lián)系之前先引入兩個概念:隱式鎖和顯式鎖。
- 隱式鎖:隱式獲取鎖柄瑰,synchronized是它的代表闸氮,使用者不需要關心其內(nèi)部鎖的獲取和釋放,所有的鎖的相關操作都由具體的關鍵字完成狱意;
- 顯式鎖:顯示地獲取鎖湖苞,Lock是它的代表,需要使用者在使用的時候顯示地獲取和釋放鎖详囤。
顯式鎖和隱式鎖都實現(xiàn)了對臨界區(qū)訪問的控制财骨,但是顯式鎖提供了更靈活、更強大的接口:
- 隱式鎖將鎖的獲取和釋放固化了藏姐,只能先獲取再釋放隆箩;顯式鎖顯然無此約束,可以按照自己的需要來做鎖的釋放羔杨;
- 顯式鎖提供了可中斷獲取鎖以及超時獲取鎖等多種隱式鎖不具備的同步特性捌臊;
- 提供維度更小的等待與喚醒(Condition)。
就Lock接口提供的synchronized關鍵字不具備的特性做一個分析描述:
特性 | 描述 |
---|---|
嘗試非阻塞獲取鎖 | 當前線程嘗試獲取鎖兜材,如果鎖未被其他線程獲取理澎,當前線程成功獲取并持有鎖 |
可中斷獲取鎖 | 獲取鎖的線程能夠響應中斷,當獲取到鎖的線程被中斷時曙寡,拋出中斷異常糠爬,鎖被釋放 |
超時獲取鎖 | 在指定的時間內(nèi)獲取鎖,如果在指定的時間內(nèi)未獲取到举庶,獲取鎖失敗执隧,返回 |
Lock的使用
案例1:
以讀寫鎖為例,Lock的使用方式很簡單户侥,只需要在需要加鎖的地方先獲取鎖镀琉,操作完成之后釋放鎖,需要注意的是:
- 要在finally中釋放鎖蕊唐,這樣做的目的是保證在獲取到鎖之后屋摔,最終都是能夠被釋放;
- 不要將獲取鎖的過程寫在try代碼塊中替梨,防止在獲取鎖發(fā)生異常時導致的鎖無故釋放钓试。
Lock api
Lock是一個接口署尤,定義了鎖的獲取和釋放等基本操作。
void lock()
線程調(diào)用該方法獲取鎖亚侠,獲取鎖后返回;void lockInterruptibly() throws InterruptedException
可中斷地獲取鎖俗扇,和lock()方法的區(qū)別在于該方法可以響應中斷硝烂;boolean tryLock()
嘗試非阻塞獲取鎖,線程調(diào)用該方法后立刻返回铜幽,成功獲取到鎖返回true滞谢,否則返回false;-
boolean tryLock(long time, TimeUnit unit) throws InterruptedException
超時獲取鎖除抛,該方法在以下3中情況會返回:- 在超時時間內(nèi)獲得鎖狮杨;
- 在超時時間被中斷;
- 超時時間結(jié)束仍未獲得到忽,返回false橄教。
void unlock()
釋放鎖;Condition newCondition()
獲取等待通知Condition組件喘漏,該組件和當前鎖綁定护蝶,只有線程獲取到了鎖才能調(diào)用await()方法,調(diào)用后翩迈,當前線程釋放鎖持灰。
jdk中Lock接口的實現(xiàn)主要包括可重入鎖和讀寫鎖,它們也都是通過AQS來完成線程的訪問控制的负饲。