標籤:取數 nbsp import 實現 類比 blocking dwr get ant
讀寫鎖介面:ReadWriteLock,它的具體實作類別為:ReentrantReadWriteLock
使用情境:
對於一個資源,讀讀能共存,讀寫不能共存,寫寫不能共存。
鎖降級:從寫鎖變成讀鎖;
鎖定擴大:從讀鎖變成寫鎖。
ReentrantReadWriteLock不支援鎖定擴大,支援鎖降級
ReadWriteLock rtLock = new ReentrantReadWriteLock(); rtLock.readLock().lock(); System.out.println("get readLock."); rtLock.writeLock().lock(); System.out.println("blocking");
會死結
ReadWriteLock rtLock = new ReentrantReadWriteLock();rtLock.writeLock().lock();System.out.println("writeLock");rtLock.readLock().lock();System.out.println("get read lock");
不會死結
案例應用:
import java.util.HashMap;import java.util.Map;import java.util.concurrent.locks.ReadWriteLock;import java.util.concurrent.locks.ReentrantReadWriteLock;public class CacheDemo { /** * 緩衝器,這裡假設需要儲存1000左右個緩衝對象,按照預設的負載因子0.75,則容量=750,大概估計每一個節點鏈表長度為5個 * 那麼數組長度大概為:150,又有雨設定map大小一般為2的指數,則最近的數字為:128 */ private Map<String, Object> map = new HashMap<>(128); private ReadWriteLock rwl = new ReentrantReadWriteLock(); public static void main(String[] args) { } public Object get(String id){ Object value = null; rwl.readLock().lock();//首先開啟讀鎖,從緩衝中去取 try{ value = map.get(id); if(value == null){ //如果緩衝中沒有釋放讀鎖,上寫鎖 rwl.readLock().unlock(); rwl.writeLock().lock(); try{ if(value == null){ //防止多寫線程重複查詢賦值 value = "redis-value"; //此時可以去資料庫中尋找,這裡簡單的類比一下 } rwl.readLock().lock(); //加讀鎖降級寫鎖,不明白的可以查看上面鎖降級的原理與保持讀取資料原子性的講解 }finally{ rwl.writeLock().unlock(); //釋放寫鎖 } } }finally{ rwl.readLock().unlock(); //最後釋放讀鎖 } return value; }}
如果不使用鎖降級功能,如先釋放寫鎖,然後獲得讀鎖,在這個get過程中,可能會有其他線程競爭到寫鎖 或者是更新資料 則獲得的資料是其他線程更新的資料,可能會造成資料的汙染,即產生髒讀的問題。
java中的讀/寫鎖