1. 程式人生 > >Java可重入鎖ReentrantLock

Java可重入鎖ReentrantLock

在JDK1.5之前,我們設計程式進行執行緒之間通訊時必須使用同步鎖,獲得同步鎖必須使用同步關鍵字synchronized(lock)的形式。JDK1.5提供了執行緒同步相關的包java.util.concurrent,引入了可重入鎖ReentrantLock,使用起來很方便並且提高了程式碼執行效率。可重入鎖ReentrantLock從概念上理解是,此鎖多執行緒可以分別分時擁有的意思,舉個簡單例程說明
在這裡插入圖片描述
我們發現執行緒A擁有鎖Lock後,執行緒A停止執行時,執行緒B可以申請到重入鎖Lock,當執行緒B停止執行時,執行緒C也可以申請到重入鎖Lock,直到T4時刻,執行緒A,B,C分別釋放重入鎖Lock。

傳統的同步鎖是不允許其他執行緒重入的,是序列的,比如執行緒A從T1到T4擁有鎖,其他執行緒在此期間是不可以申請到鎖的。
在這裡插入圖片描述
重入鎖ReentrantLock
在這裡插入圖片描述
執行緒間通訊
重入鎖ReentrantLock使用Condition進行執行緒間通訊,傳統鎖使用wait,notify進行執行緒間通訊。

Condition類的awiat方法=Object類的wait方法
Condition類的signal方
=Object類的notify方法
Condition類的signalAll方法===Object類的notifyAll方法
在這裡插入圖片描述
例程中呼叫condition.await(),執行緒將一直等待下去,不會結束程式,condition還可以等待一定時間。
在這裡插入圖片描述


上面例程中執行緒等待5秒鐘後結束執行。

喚起執行緒執行使用condition.signal();
在這裡插入圖片描述
使用Condition進行執行緒間通訊,各執行緒必須共享同一個Condition物件。這個有點類似傳統的同步鎖。

ReentrantLock鎖型別

Lock lock=new ReentrantLock(true);//公平鎖 Lock lock=new ReentrantLock(false);//非公平鎖

ReentrantLock鎖其他方法
getHoldCount() 查詢當前執行緒保持此鎖的次數,也就是執行此執行緒執行lock方法的次數
getQueueLength()返回正等待獲取此鎖的執行緒估計數,比如啟動10個執行緒,1個執行緒獲得鎖,此時返回的是9
getWaitQueueLength(Condition condition)返回等待與此鎖相關的給定條件的執行緒估計數。比如10個執行緒,用同一個condition物件,並且此時這10個執行緒都執行了condition物件的await方法,那麼此時執行此方法返回10
hasWaiters(Condition condition)查詢是否有執行緒等待與此鎖有關的給定條件(condition),對於指定contidion物件,有多少執行緒執行了condition.await方法
hasQueuedThread(Thread thread)查詢給定執行緒是否等待獲取此鎖
hasQueuedThreads()是否有執行緒等待此鎖
isFair()該鎖是否公平鎖
isHeldByCurrentThread() 當前執行緒是否保持鎖鎖定,執行緒的執行lock方法的前後分別是false和true
isLock()此鎖是否有任意執行緒佔用
lockInterruptibly()如果當前執行緒未被中斷,獲取鎖
tryLock()嘗試獲得鎖,僅在呼叫時鎖未被執行緒佔用,獲得鎖
tryLock(long timeout TimeUnit unit)如果鎖在給定等待時間內沒有被另一個執行緒保持,則獲取該鎖

演示例程
在這裡插入圖片描述
執行結果
在這裡插入圖片描述
可以發現,重入鎖等待佇列中的執行緒從0增加到9,每一個執行緒休眠5秒鐘,所有的10個執行緒都分別一次擁有了重入鎖,其他執行緒等待時其他執行緒就可以擁有重入鎖,所以所有執行緒列印的資訊幾乎時同一時間。
如果將condition.await(5,TimeUnit.SECONDS)替換成Thread.sleep(5000),執行結果變成如下
在這裡插入圖片描述
可以發現各執行緒列印資訊的時間相差5秒鐘,應該沒有使用ReentrantLock的功能。