概述
1、API在JDK的java.util.concurrent.locks下。
2、不是Java關鍵字,是接口。
3、ReentrantLock是JDK唯一實現了Lock接口的類。
public interface Lock {//獲取鎖void lock();//可以響應中斷的鎖void lockInterruptibly() throws InterruptedException;//嘗試獲取鎖boolean tryLock();//嘗試獲取鎖,如果拿不到會等待time的時間boolean tryLock(long time, TimeUnit unit) throws InterruptedException;//釋放鎖void unlock();
}
四個獲取鎖方法
lock()
是平常使用得最多的一個方法,就是用來獲取鎖。如果鎖已被其他線程獲取,則進行等待。
由于在前面講到如果采用Lock,必須主動去釋放鎖,并且在發生異常時,不會自動釋放鎖。因此一般來說,使用Lock必須在try{}catch{}塊中進行,并且將釋放鎖的操作放在finally塊中進行,以保證鎖一定被被釋放,防止死鎖的發生。
實例:http://blog.csdn.net/zengmingen/article/details/53257891
tryLock()
是有返回值的,它表示用來嘗試獲取鎖,如果獲取成功,則返回true,如果獲取失敗(即鎖已被其他線程獲取),則返回false,也就說這個方法無論如何都會立即返回。在拿不到鎖時不會一直在那等待。
實例:http://blog.csdn.net/zengmingen/article/details/53259279
tryLock(long time, TimeUnit unit)
和tryLock()方法是類似的,只不過區別在于這個方法在拿不到鎖時會等待一定的時間,在時間期限之內如果還拿不到鎖,就返回false。如果如果一開始拿到鎖或者在等待期間內拿到了鎖,則返回true。
實例:http://blog.csdn.net/zengmingen/article/details/53259394
lockInterruptibly()
比較特殊,當通過這個方法去獲取鎖時,如果其他線程正在等待獲取鎖,則這個線程能夠響應中斷,即中斷線程的等待狀態。也就使說,當兩個線程同時通過
lockInterruptibly()想獲取某個鎖時,假若此時線程A獲取到了鎖,而線程B只有等待,那么對線程B調用threadB.interrupt()方法能夠中斷線程B的等待過程。
【注意:等待的那個線程B可以被中斷,不是正在執行的A線程被中斷。
注意,當一個線程獲取了鎖之后,是不會被interrupt()方法中斷的。
因此當通過lockInterruptibly()方法獲取某個鎖時,如果不能獲取到,只有進行等待的情況下,是可以響應中斷的。
而用synchronized修飾的話,當一個線程處于等待某個鎖的狀態,是無法被中斷的,只有一直等待下去。】
實例:http://blog.csdn.net/zengmingen/article/details/53260650
Lock和synchronized的選擇
1)Lock是一個接口,而synchronized是Java中的關鍵字,synchronized是內置的語言實現。2)synchronized在發生異常時,會自動釋放線程占有的鎖,因此不會導致死鎖現象發生。
而Lock在發生異常時,如果沒有主動通過unLock()去釋放鎖,則很可能造成死鎖現象,因此使用Lock時需要在finally塊中釋放鎖。
3)Lock可以讓等待鎖的線程響應中斷,而synchronized卻不行,使用synchronized時,等待的線程會一直等待下去,不能夠響應中斷;
4)通過Lock可以知道有沒有成功獲取鎖,而synchronized卻無法辦到。
5)Lock可以提高多個線程進行讀操作的效率。
在性能上來說,如果競爭資源不激烈,兩者的性能是差不多的,而當競爭資源非常激烈時(即有大量線程同時競爭),此時Lock的性能要遠遠優于synchronized。在具體使用時要根據適當情況選擇。