在Java5.0之前,只有synchronized(內建鎖)和volatile. Java5.0後引入了顯示鎖ReentrantLock.
ReentrantLock概況
ReentrantLock是可重入的鎖,它不同於內建鎖, 它在每次使用都需要顯示的加鎖和解鎖, 而且提供了更高階的特性:公平鎖, 定時鎖, 有條件鎖, 可輪詢鎖, 可中斷鎖. 可以有效避免死鎖的活躍性問題trantLock實現了
Lock介面:
複製程式碼 程式碼如下:
public interface Lock {
//阻塞直到獲得鎖或者中斷
void lock();
//阻塞直到獲得鎖或者中斷拋異常
void lockInterruptibly() throws InterruptedException;
//只有鎖可用時才獲得,否則直接返回
boolean tryLock();
//只有鎖在指定時間內可用時才獲得,否則直接返回,中斷時拋異常
boolean tryLock(long time, TimeUnit unit) throws InterruptedException;
void unlock();
//返回一個繫結在這個鎖上的條件
Condition newCondition();
}
Lock使用
複製程式碼 程式碼如下:
Lock lock = new ReentrantLock();
();
try{
//更新物件狀態
}finally{
//這裡注意,一定要有finally程式碼塊去解鎖
//否則容易造成死鎖等活躍性問題
ck();
}
ReentrantLock特性
輪詢鎖的和定時鎖
可輪詢和可定時的鎖請求是通過tryLock()方法實現的,和無條件獲取鎖不一樣. ReentrantLock可以有靈活的容錯機制.死鎖的很多情況是由於順序鎖引起的, 不同執行緒在試圖獲得鎖的時候阻塞,並且不k16-0.html" target="_blank" >釋放自己已經持有的鎖, 最後造成死鎖. tryLock()方法在試圖獲得鎖的時候,如果該鎖已經被其它執行緒持有,則按照設定方式立刻返回,而不是一直阻塞等下去,同時在返回後釋放自己持有的鎖.可以根據返回的結果進行重試或者取消,進而避免死鎖的發生.
公平性
ReentrantLock建構函式中提供公平性鎖和非公平鎖(預設)兩種選擇。所謂公平鎖,執行緒將按照他們發出請求的順序來獲取鎖,不允許插隊;但在非公平鎖上,則允許插隊:當一個執行緒發生獲取鎖的.請求的時刻,如果這個鎖是可用的,那這個執行緒將跳過所在佇列裡等待執行緒並獲得鎖。我們一般希望所有鎖是非公平的。因為當執行加鎖操作時,公平性將講由於執行緒掛起和恢復執行緒時開銷而極大的降低效能。考慮這麼一種情況:A執行緒持有鎖,B執行緒請求這個鎖,因此B執行緒被掛起;A執行緒釋放這個鎖時,B執行緒將被喚醒,因此再次嘗試獲取鎖;與此同時,C執行緒也請求獲取這個鎖,那麼C執行緒很可能在B執行緒被完全喚醒之前獲得、使用以及釋放這個鎖。這是種雙贏的局面,B獲取鎖的時刻(B被喚醒後才能獲取鎖)並沒有推遲,C更早地獲取了鎖,並且吞吐量也獲得了提高。在大多數情況下,非公平鎖的效能要高於公平鎖的效能。
可中斷獲鎖獲取操作
lockInterruptibly方法能夠在獲取鎖的同時保持對中斷的響應,因此無需建立其它型別的不可中斷阻塞操作。
讀寫鎖ReadWriteLock
ReentrantLock是一種標準的互斥鎖,每次最多隻有一個執行緒能持有鎖。讀寫鎖不一樣,暴露了兩個Lock物件,其中一個用於讀操作,而另外一個用於寫操作。
複製程式碼 程式碼如下:
public interface ReadWriteLock {
/**
* Returns the lock used for reading.
*
* @return the lock used for reading.
*/
Lock readLock();
/**
* Returns the lock used for writing.
*
* @return the lock used for writing.
*/
Lock writeLock();
}
可選擇實現:
1.釋放優先
2.讀執行緒插隊
3.重入性
4.降級
5.升級
ReentrantReadWriteLock實現了ReadWriteLock介面,構造器提供了公平鎖和非公平鎖兩種建立方式。讀寫鎖適用於讀多寫少的情況,可以實現更好的併發性。
示例
複製程式碼 程式碼如下:
public class ReadWriteMap{
private Mapmap;
private final ReadWriteLock lock = new ReentrantReadWriteLock();
private final Lock readLock = Lock();
private final Lock writeLock = eLock();
public ReadWriteMap(Mapmap) {
= map;
}
public V get(K key) {
();
try {
return (key);
} finally {
ck();
}
}
public void put(K key, V value) {
();
try {
(key, value);
} finally {
ck();
}
}
}