Lock
位於java.util.concurrent.locks
包下,是一種線程同步機制,就像synchronized
塊同樣。可是,Lock
比synchronized
塊更靈活、更復雜。java
話很少說,咱們直接來看官方文檔對Lock接口相關概念及功能的描述,今天又是看英文文檔,翻譯理解的一天。編程
void lock()api
獲取鎖。若是鎖不可用,則當前線程將出於線程調度目的而禁用,並處於休眠狀態,直到得到鎖爲止。安全
void lockInterruptibly() throws InterruptedException;併發
若是當前線程未被中斷,則獲取鎖。若是鎖可用,則獲取鎖並當即返回。函數
若是鎖不可用,出於線程調度目的,將禁用當前線程,該線程將一直處於休眠狀態。性能
下面兩種情形會讓當前線程中止休眠狀態:優化
鎖由當前線程獲取。.net
其餘一些線程中斷當前線程,而且支持對鎖獲取的中斷。線程
當前線程出現下面兩種狀況時,將拋出InterruptedException
,並清除當前線程的中斷狀態。
當前線程在進入此方法時,已經設置爲中斷狀態。
當前線程在獲取鎖時被中斷,而且支持對鎖獲取中斷。
boolean tryLock();
嘗試獲取鎖,若是鎖處於空閒狀態,則獲取鎖,並當即返回true。若是鎖不可用,則當即返回false。
該方法的典型使用:
Lock lock = ...; //確保鎖在被獲取時被解鎖 if (lock.tryLock()) { try { // manipulate protected state } finally { lock.unlock(); } } else { // perform alternative actions }
boolean tryLock(long time, TimeUnit unit) throws
InterruptedException;
該方法爲tryLock()的重載方法,兩個參數分別表示爲:
若是在給定的等待時間內是空閒的而且當前線程沒有被中斷,則獲取鎖。若是鎖可用,則此方法當即獲取鎖並返回true,若是鎖不可用,出於線程調度目的,將禁用當前線程,該線程將一直處於休眠狀態。
下面三種情形會讓當前線程中止休眠狀態:
鎖由當前線程獲取。
到了指定的等待時間。
當前線程出現下面兩種狀況時,將拋出InterruptedException,並清除當前線程的中斷狀態。
當前線程在進入此方法時,已經設置爲中斷狀態。
當前線程在獲取鎖時被中斷,而且支持對鎖獲取中斷。
若是指定的等待時間超時,則返回false值。若是時間小於或等於0,則該方法永遠不會等待。
void unlock()
釋放鎖,與lock()、tryLock()、tryLock(long , TimeUnit)、lockInterruptibly()相對應。
Condition newCondition()
返回綁定到此鎖實例的Condition實例。當前線程只有得到了鎖,才能調用Condition實例的await()方法,並釋放鎖。
顧名思義,ReentrantLock是重入鎖,關於這個重入鎖,以前涉及過一些知識,在這裏作整合,並稍微地補充一下。
ReentrantLock
位於java.util.concurrent(J.U.C)
包下,是Lock接口的實現類。基本用法與synchronized
類似,都具有可重入互斥的特性,但擁有擴展的功能。
RenntrantLock推薦的基本寫法:
class X { //定義鎖對象 private final ReentrantLock lock = new ReentrantLock(); // ... //定義須要保證線程安全的方法 public void m() { //加鎖 lock.lock(); try{ // 保證線程安全的代碼 } // 使用finally塊保證釋放鎖 finally { lock.unlock() } } }
ReentrantLock表現爲API層面的互斥鎖,經過lock()
和unlock()
方法完成,是顯式的,而synchronized表現爲原生語法層面的互斥鎖,是隱式的。
重進入意味着:任意線程在獲取到鎖以後可以再次獲取該鎖而不會被鎖阻塞,synchronized
和Reentrant都是可重入的,隱式顯式之分。
實現可重入須要解決的兩個關鍵部分:
關於鎖公平的部分,官方文檔是這樣描述的(英文我就不貼了),詞彙較簡單,我試着翻譯一下:
Reentrant類的構造函數接受一個可選的公平性參數fair。這時候就出現兩種選擇:
公平鎖每每體現處的整體吞吐量比非公平鎖要低,也就是更慢。
鎖的公平性並不保證線程調度的公平性,但公平鎖可以減小"飢餓"發生的機率。
須要注意的是:不定時的tryLock()方法不支持公平性設置。若是鎖可用,即便其餘線程等待時間比它長,它也會成功得到鎖。
當持有線程長期不釋放鎖的時候,正在等待的線程可以選擇放棄等待或處理其餘事情。
一個ReentrantLock對象能夠經過newCondition()同時綁定多個Condition對象。
JDK1.6以前,ReentrantLock在性能方面是要領先於synchronized鎖的,可是JDK1.6及以後版本實現了各類鎖優化技術,可參考:
聊聊併發Java SE1.6中的Synchronized,後續性能改進會更加偏向於原生的synchronized。
參考資料: 《深刻理解Java虛擬機》周志明 《Java併發編程的藝術》方騰飛