第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

首頁 慕課教程 Java并發(fā)工具 Java并發(fā)工具 可重入讀寫鎖 ReentrantReadWrite

可重入讀寫鎖 ReentrantReadWriteLock

1. 前言

從本節(jié)開始,我們學(xué)習(xí)新一章內(nèi)容 —— 并發(fā)鎖。
在 “Java 并發(fā)原理入門教程” 中,介紹了鎖相關(guān)概念和原理知識,本章各小節(jié)內(nèi)容不再過多解釋概念,重點為大家介紹具體鎖工具的 API 和使用方法。

本節(jié)帶領(lǐng)大家認識第一個常用的 Java 并發(fā)鎖工具之 ReentrantReadWriteLock。

本節(jié)先簡單介紹 ReentrantReadWriteLock 的基本概念,然后介紹關(guān)鍵的編程方法,最后通過一個編程例子為大家展示 ReentrantReadWriteLock 工具類的用法。

下面我們正式開始介紹吧。

2. 概念解釋

ReadWriteLock 是一個接口類型,翻譯為 “讀寫鎖”。多個線程同時讀某個資源時,為了滿足并發(fā)量,不應(yīng)該加鎖處理,但是如果有一個線程寫這個資源,就不應(yīng)該再有其它線程對該資源進行讀操作或者寫操作。
實現(xiàn)了此接口的類提供了 “讀讀能共存、讀寫不能共存、寫寫不能共存” 的控制邏輯。當(dāng)同一個資源被大量線程讀取,但僅有少數(shù)線程修改時,使用 ReadWriteLock 可大大提高并發(fā)效率。比如對一個電商網(wǎng)站的商品,回復(fù)評論(寫)是不頻繁的,但是瀏覽(讀)是非常頻繁的,這種情況使用 ReadWriteLock 工具類做并發(fā)控制非常適合??傊m合讀多寫少的場景。

ReentrantLock 翻譯為 “可重入鎖”?!翱芍厝搿?是什么意思呢?就是指一個線程可以多次獲取該鎖,Java 中 在語言語法層提供的 syncrinized 是最常見的用于并發(fā)控制的關(guān)鍵字,其構(gòu)成的鎖也是可重入的??芍厝腈i在一定程度可以避免死鎖的發(fā)生。

更多關(guān)于鎖的原理,可閱讀 “Java 并發(fā)原理入門教程”。

ReentrantReadWriteLock 類實現(xiàn)了 “讀寫鎖” 和 “可重入鎖” 的雙重功能。其本身不提供加鎖服務(wù),只負責(zé)提供讀鎖和寫鎖。在介紹關(guān)鍵編程方法之前,我們先看一張圖整體了解關(guān)鍵方法的使用方式。
圖片描述
下面我們學(xué)習(xí)其關(guān)鍵的編程方法。

3.ReentrantReadWriteLock 的編程方法

  1. 構(gòu)造方法 ReentrantReadWriteLock () 和 ReentrantReadWriteLock (boolean fair)
    有兩個構(gòu)造方法,在構(gòu)造對象時,可選擇是否構(gòu)造為公平鎖模式。什么是公平鎖呢?公平鎖指的是獲取所的線程按照申請鎖的線程獲取,而非亂序隨機獲取到鎖權(quán)限。

  2. writeLock () 和 readLock ()
    這兩個方法分別用于獲取寫鎖和獲取讀鎖,對讀操作的邏輯使用讀鎖對象加鎖,對寫操作的邏輯使用寫鎖對象加鎖,如此可以做到 “讀讀能共存、讀寫不能共存、寫寫不能共存”,在實現(xiàn)線程安全的情況下,提高并發(fā)效率。

  3. isFair()
    獲取鎖是否具有公平性,此方法返回 boolean 值。

  4. getWriteHoldCount () 、 getReadHoldCount () 和 getReadLockCount ()
    getWriteHoldCount () 方法用于獲取當(dāng)前線程的寫鎖計數(shù),getReadHoldCount () 方法用于獲取當(dāng)前線程的讀鎖計數(shù),getReadLockCount () 方法用于獲取總的讀鎖計數(shù)。所有方法均返回 int 值。

4.ReentrantReadWriteLock.ReadLock 的編程方法

此類是一個靜態(tài)內(nèi)部類,封裝在 ReentrantReadWriteLock 中,此類不對外提供構(gòu)造方法,由 ReentrantReadWriteLock.readLock () 方法獲取此類對象。

  1. lock () 和 lockInterruptibly ()
    兩個方法都用于加讀鎖,第二個方法可被中斷。

  2. tryLock () 和 tryLock (long timeout, TimeUnit unit)
    兩個方法都返回 boolean 值,用于嘗試加讀鎖,第一個方法在嘗試不成功時立刻返回,第二個方法可在指定時間內(nèi)嘗試加讀鎖。這兩個方法提供了加鎖的柔性,提供了更多操作空間。

  3. unlock()
    釋放讀鎖。

5.ReentrantReadWriteLock.WriteLock 的編程方法

此類是一個靜態(tài)內(nèi)部類,封裝在 ReentrantReadWriteLock 中,此類不對外提供構(gòu)造方法,由 ReentrantReadWriteLock.writeLock () 方法獲取此類對象。

  1. lock () 和 lockInterruptibly ()
    兩個方法都用于加寫鎖,第二個方法可被中斷。

  2. tryLock () 和 tryLock (long timeout, TimeUnit unit)
    兩個方法都返回 boolean 值,用于嘗試加寫鎖,第一個方法在嘗試不成功時立刻返回,第二個方法可在指定時間內(nèi)嘗試加寫鎖。這兩個方法提供了加鎖的柔性,提供了更多操作空間。

  3. unlock()
    釋放寫鎖。

6. 編程案例

上面介紹了核心編程方法,我們舉一個編程案例,實際體會一下 ReentrantReadWriteLock 的用法。

import lombok.SneakyThrows;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

public class ReadWriteLockTest {

    // 創(chuàng)建讀寫鎖對象
    private final ReadWriteLock readWriteLock = new ReentrantReadWriteLock();
    // 獲取讀鎖對象
    private final Lock readlock = readWriteLock.readLock();
    // 獲取寫鎖對象
    private final Lock writelock = readWriteLock.writeLock();
    // 待控制的資源
    private int account = 0;

    private static ReadWriteLockTest readWriteLockTest = new ReadWriteLockTest();

    public static void main(String[] args) {
        new Thread(new Runnable() {
            @SneakyThrows
            public void run() {
                while(true) {
                    Thread.sleep(1000);
                    int tmp = readWriteLockTest.get();
                    System.out.println("讀操作:" + tmp);
                }
            }
        }).start();

        new Thread(new Runnable() {
            @SneakyThrows
            public void run() {
                while(true) {
                    Thread.sleep(2000);
                    readWriteLockTest.add(10);
                }
            }
        }).start();
    }

    public void add(int value) {
        // 加寫鎖
        writelock.lock();
        try {
            account += 1;
        } finally {
            // 釋放寫鎖
            writelock.unlock();
        }
    }

    public int get() {
        // 加讀鎖
        readlock.lock();
        try {
            return account;
        } finally {
            // 釋放讀鎖
            readlock.unlock();
        }
    }
}

運行上面代碼一段時間后結(jié)果如下:

讀操作:0
讀操作:1
讀操作:1
讀操作:2
讀操作:2

注意在使用時,獲取鎖的操作 lock () 應(yīng)該放在 try 之前,而釋放鎖的操作 unlock () 需要放在 finally 中,可確保鎖釋放。

7. 小結(jié)

本節(jié)解釋了 ReentrantReadWriteLock 的基本概念和應(yīng)用場合,且通過一個簡單的例子展示了其用法,更多關(guān)于此工具類的概念和原理介紹,可閱讀 “Java 并發(fā)原理入門教程” 。希望大家在學(xué)習(xí)過程中,多思考勤練習(xí),早日掌握之。