1.讀寫鎖
讀寫鎖在同一個時刻可以擁有多個讀線程訪問,但是在寫線程訪問時,所有的讀線程和其他寫線程均被阻塞。讀寫鎖維護了一對鎖,一個讀鎖和一個寫鎖,通過讀鎖和寫鎖,事得併發性比一般的排它鎖有了很大提升。
-
java併發包提供的讀寫鎖實現是ReentranWriteLock(特性):
- 公平性選則
- 重入性
- 鎖降級
2.多寫鎖示例
ReadWriteLock僅定義了獲取鎖和寫鎖的兩個方法,即readLock()和writeLock方法。
package cn.smallmartial.concurrency;
import jdk.nashorn.internal.ir.CallNode;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
/**
* @Author smallmartial
* @Date 2019/8/26
* @Email [email protected]
*/
public class Cache {
static Map<String,Object> map= new HashMap<String,Object>();
static ReentrantReadWriteLock rwl= new ReentrantReadWriteLock();
static Lock r= rwl.readLock();
static Lock w= rwl.writeLock();
//獲取一個key對應的value
public static final Object get(String key){
r.lock();
try {
return map.get(key);
}finally {
r.unlock();
}
}
//設置key對應的value,並且返回舊的value
public static final Object put(String key,Object values){
w.lock();
try {
return map.put(key,values);
} finally {
w.unlock();
}
}
//清空所有的內容
public static final void clear(){
w.lock();
try {
map.clear();
}finally {
w.unlock();
}
}
}
3.讀寫鎖的實現
-
讀寫狀態的設計
讀寫鎖依賴自定義同步器來實現同步功能,而讀寫狀態就是其同步器的同步狀態。讀寫鎖需要在同步狀態上維護多個讀線程和一個寫線程的狀態,使得改狀態的設計成爲讀寫鎖實現的關鍵。
-
寫鎖的獲取與釋放
寫鎖是一個支持重入的排它鎖,如果當前線程已經獲取了寫鎖,則增加寫狀態。如果當前線程在獲取寫鎖時,讀鎖已經被獲取(讀狀態不爲0)或者該線程不是已經獲取寫鎖的線程,則當前線程進入等待狀態。(只用當其他讀線程都釋放了讀鎖,寫鎖才能被當前線程獲取,而寫鎖一旦獲取,則其他讀寫線程的後續訪問均被阻塞)
-
讀鎖的獲取與釋放
讀鎖是一個支持重進入的共享鎖,它能夠被多個線程同時獲取,在沒有其他寫線程訪問(或者寫線程爲0)時,讀鎖總會被成功的獲取,而所做的也至少增加讀狀態。
-
鎖降級
鎖降級是指寫鎖降級爲讀鎖。如果當前線程擁有寫鎖,然後將其釋放,最後再獲取讀鎖,這種分段完成的過程不能稱之爲鎖降級。鎖降級是指把持住寫鎖,在獲取讀鎖,隨後釋放寫鎖。