ReentrantReadWriteLock了解

Java鎖概念

在講這個類之前先簡單說一下Java并發兩個概念,共享鎖,排他鎖(獨占鎖)。共享鎖就可以同時被多個線程占有的鎖,即允許多個線程同時獲取鎖,同時訪問資源,常見類:CountDownLatch。排他鎖就是在任何時刻只允許一個線程能獲取鎖,其他的線程都在等待獲取,必須等到這個鎖持有者釋放了,才能獲取到鎖,常見類:ReentrantLock。

ReentrantReadWriteLock介紹

ReentrantReadWriteLock 是Java的讀寫鎖,擁有共享鎖和排他鎖的功能,但并不是完全的共享鎖和排他鎖。通過分離讀寫鎖,讓多線程可以并發訪問讀鎖,在訪問寫鎖的時候,讀寫互斥,起到保護數據的目的。主要應用場景是:當很多線程從每個數據結構讀取數據,而很少有線程對其進行修改時,在這種情況下,允許讀取線程共享訪問你是合適的,寫入器線程依然是互斥。

ReentrantReadWriteLock 主要特性

公平性

支持公平鎖和非公平鎖,默認是非公平鎖,可以根據構造方式設置公平鎖。

  ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock(true);//默認是false 非公平鎖

由于讀線程之間沒有鎖競爭,所以讀操作,沒有公平性和非公平性。寫操作時可能立即獲取到鎖,所以會推遲一個或者多個讀操作或者寫操作,非公平鎖的吞吐量要高于公平鎖。

重入性

讀寫鎖允許讀線程和寫線程按照請求鎖的順序重新獲取讀取鎖或者寫入鎖,但是只有寫線程釋放了鎖,讀線程才能獲取重入鎖。寫線程獲取寫入鎖以后可以再次獲取讀鎖,但是讀線程獲取讀鎖后不能獲取寫入鎖。讀寫鎖最多支持65535個遞歸寫入鎖和65535個遞歸讀取鎖。

鎖降級

寫線程獲取鎖后,可以獲取讀線程,然后再釋放寫鎖,這樣就從寫鎖變成讀鎖,實現了鎖降級。

鎖升級

讀線程獲取鎖后,并不知直接獲取寫鎖,獲取一個寫入鎖需要釋放所有讀取鎖。從讀取鎖升級到寫入鎖,這個過程被稱作鎖升級,這個過程必須讀取鎖釋放了鎖,在重新獲取到寫入鎖,才能稱作鎖升級。

鎖獲取中斷

讀取鎖和寫入鎖都支持在獲取鎖期間被中斷。

概括起來其實就是讀寫鎖的機制

讀讀不互斥,即使當前有100個線程同時讀取資源,沒有線程寫入,這個100個線程是可以并發訪問。
讀寫互斥,比如說當前有線程在寫,當線程想獲取讀入鎖的時候,會被堵塞,反過來,有線程已經獲取讀入鎖的時候,寫的線程也會堵塞,就看誰先拿到鎖。
寫寫互斥比如有兩個線程A,B,A線程先拿到鎖,B線程就會堵塞到A釋放鎖為止。
使用ReentrantReadWriteLock讀取緩存例子

 private final ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock();
    
    private final Map<String,Object> map = new HashMap<>(); //假設這存著數據緩存
    
    public Object readwrite(String id) {
        Object val = null;
        rwLock.readLock().lock(); //首先開啟讀取鎖,從緩存中去讀取
        try {
            val = map.get(id);
            if(val == null) {//假如緩存中沒有這個值,可以從數據庫讀取這個值,然后寫入到緩存中
                rwLock.readLock().unlock();//這里用到的鎖升級,先釋放,在獲取
                rwLock.writeLock().lock();
                try {
                    //這里是從數據庫獲取數據
                    val = "aaa";
                }finally {
                    rwLock.writeLock().unlock();//釋放寫入鎖,讓緩存可以并發訪問
                }
                rwLock.readLock().lock();
            }
        }finally {
            rwLock.readLock().unlock();//兩次讀取鎖,保證釋放鎖,一定都在finally中可以釋放
        }
        return val;
    }
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • ReadWriteLock 從這一節開始介紹鎖里面的最后一個工具:讀寫鎖(ReadWriteLock)。 Reen...
    raincoffee閱讀 652評論 0 1
  • 一、前言 借用Java并發編程實踐中的話"編寫正確的程序并不容易,而編寫正常的并發程序就更難了",相比于順序執行的...
    運維開發筆記閱讀 355評論 0 2
  • Nginx + Apache 反向代理 反向代理負載均衡 使用代理服務器可以將請求轉發給內部的Web服務器,使用這...
    食屎啦你_91ad閱讀 611評論 0 1
  • 難眠的夜 失聲的淚 一切美好被時光吞沒 那時的你青澀稚嫩 如今的你人老珠黃 我站在橋的這頭 思念著對面的你 多少次...
    紅豆薏米綠豆閱讀 144評論 0 3