国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

通俗易懂讀寫鎖ReentrantReadWriteLock的使用

這篇具有很好參考價(jià)值的文章主要介紹了通俗易懂讀寫鎖ReentrantReadWriteLock的使用。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問(wèn)。

概述

ReentrantReadWriteLock不知道大家熟悉嗎?其實(shí)在實(shí)際的項(xiàng)目中用的比較少,反正我所在的項(xiàng)目沒(méi)有用到過(guò)。

ReentrantReadWriteLock稱為讀寫鎖,它提供一個(gè)讀鎖,支持多個(gè)線程共享同一把鎖。它也提供了一把寫鎖,是獨(dú)占鎖,和其他讀鎖或者寫鎖互斥,表明只有一個(gè)線程能持有鎖資源。通過(guò)兩把鎖的協(xié)同工作,能夠最大化的提高讀寫的性能,特別是讀多寫少的場(chǎng)景,而往往大部分的場(chǎng)景都是讀多寫少的。

本文主要講解ReentrantReadWriteLock的使用和應(yīng)用場(chǎng)景。

ReentrantReadWriteLock介紹

ReentrantReadWriteLock實(shí)現(xiàn)了ReadWriteLock接口,可以獲取到讀鎖(共享鎖),寫鎖(獨(dú)占鎖)。同時(shí),通過(guò)構(gòu)造方法可以創(chuàng)建鎖本身是公平鎖還是非公鎖。

讀寫鎖機(jī)制:

讀鎖 寫鎖
讀鎖 共享 互斥
寫鎖 互斥 互斥

線程進(jìn)入讀鎖的前提條件:

  • 沒(méi)有其他線程的寫鎖
  • 沒(méi)有寫請(qǐng)求,或者有寫請(qǐng)求但調(diào)用線程和持有鎖的線程是同一個(gè)線程

進(jìn)入寫鎖的前提條件:

  • 沒(méi)有其他線程的讀鎖
  • 沒(méi)有其他線程的寫鎖

鎖升級(jí)、降級(jí)機(jī)制:

我們知道ReentrantLock具備可重入的能力,即同一個(gè)線程多次獲取鎖,不引起阻塞,那么ReentrantReadWriteLock關(guān)于可重入性是怎么樣的呢?

關(guān)于這個(gè)問(wèn)題需要引入兩個(gè)概念,鎖升級(jí),鎖降級(jí)。

  • 鎖升級(jí):從讀鎖變成寫鎖。
  • 鎖降級(jí):從寫鎖變成讀鎖;

重入時(shí)鎖升級(jí)不支持:持有讀鎖的情況下去獲取寫鎖會(huì)導(dǎo)致獲取寫鎖永久等待,需要先釋放讀,再去獲得寫

重入時(shí)鎖降級(jí)支持:持有寫鎖的情況下去獲取讀鎖,造成只有當(dāng)前線程會(huì)持有讀鎖,因?yàn)閷戞i會(huì)互斥其他的鎖

API介紹

構(gòu)造方法:

  • public ReentrantReadWriteLock():默認(rèn)構(gòu)造方法,非公平鎖
  • public ReentrantReadWriteLock(boolean fair):true 為公平鎖

常用API:

  • public ReentrantReadWriteLock.ReadLock readLock():返回讀鎖
  • public ReentrantReadWriteLock.WriteLock writeLock():返回寫鎖
  • public void lock():加鎖
  • public void unlock():解鎖
  • public boolean tryLock():嘗試獲取鎖

代碼范式

  • 加解鎖格式
r.lock();
try {
    // 臨界區(qū)
} finally {
	r.unlock();
}
復(fù)制代碼
  • 鎖降級(jí)
w.lock();
try {
    r.lock();// 降級(jí)為讀鎖, 釋放寫鎖, 這樣能夠讓其它線程讀取緩存
    try {
        // ...
    } finally{
    	w.unlock();// 要在寫鎖釋放之前獲取讀鎖
    }
} finally{
	r.unlock();
}
復(fù)制代碼

實(shí)戰(zhàn)案例

驗(yàn)證讀讀共享模式

@Test
    public void readReadMode() throws InterruptedException {
        ReentrantReadWriteLock rw = new ReentrantReadWriteLock();
        ReentrantReadWriteLock.ReadLock r = rw.readLock();
        ReentrantReadWriteLock.WriteLock w = rw.writeLock();

        Thread thread0 = new Thread(() -> {
            r.lock();
            try {
                Thread.sleep(1000);
                System.out.println("Thread 1 running " + new Date());
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                r.unlock();
            }
        },"t1");

        Thread thread1 = new Thread(() -> {
            r.lock();
            try {
                Thread.sleep(1000);
                System.out.println("Thread 2 running " + new Date());
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                r.unlock();
            }
        },"t2");

        thread0.start();
        thread1.start();

        thread0.join();
        thread1.join();
    }
復(fù)制代碼

運(yùn)行結(jié)果:

通俗易懂讀寫鎖ReentrantReadWriteLock的使用

  • 兩個(gè)線程同時(shí)運(yùn)行,都獲取到了讀鎖

驗(yàn)證讀寫互斥模式

@Test
    public void readWriteMode() throws InterruptedException {
        ReentrantReadWriteLock rw = new ReentrantReadWriteLock();
        ReentrantReadWriteLock.ReadLock r = rw.readLock();
        ReentrantReadWriteLock.WriteLock w = rw.writeLock();

        Thread thread0 = new Thread(() -> {
            r.lock();
            try {
                Thread.sleep(1000);
                System.out.println("Thread 1 running " + new Date());
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                r.unlock();
            }
        },"t1");

        Thread thread1 = new Thread(() -> {
            w.lock();
            try {
                Thread.sleep(1000);
                System.out.println("Thread 2 running " + new Date());
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                w.unlock();
            }
        },"t2");

        thread0.start();
        thread1.start();

        thread0.join();
        thread1.join();
    }
復(fù)制代碼

運(yùn)行結(jié)果:

通俗易懂讀寫鎖ReentrantReadWriteLock的使用

  • 兩個(gè)線程間隔1秒,互斥執(zhí)行

真實(shí)緩存例子

什么場(chǎng)景下讀多寫少? 想必最先想到的就是緩存把,ReentrantReadWriteLock在緩存場(chǎng)景中就是一個(gè)很典型的應(yīng)用。

通俗易懂讀寫鎖ReentrantReadWriteLock的使用

緩存更新時(shí),是先清緩存還是先更新數(shù)據(jù)庫(kù)?

  • 先清緩存:可能造成剛清理緩存還沒(méi)有更新數(shù)據(jù)庫(kù),高并發(fā)下,其他線程直接查詢了數(shù)據(jù)庫(kù)過(guò)期數(shù)據(jù)到緩存中,這種情況非常嚴(yán)重,直接導(dǎo)致后續(xù)所有的請(qǐng)求緩存和數(shù)據(jù)庫(kù)不一致。
  • 先更新?lián)?kù):可能造成剛更新數(shù)據(jù)庫(kù),還沒(méi)清空緩存就有線程從緩存拿到了舊數(shù)據(jù),這種情況概率比較小,影響范圍有限,只對(duì)這一次的查詢結(jié)果有問(wèn)題。

顯而易見,通常情況下,先更新數(shù)據(jù)庫(kù),然后清空緩存。

public class GenericCachedDao {

    // 緩存對(duì)象,這里用jvm緩存
    Map<String, String> cache = new HashMap<>();
    // 讀寫鎖
    ReadWriteLock readWriteLock = new ReentrantReadWriteLock();

    // 讀取操作
    public String getData(String key) {
        // 加讀鎖,防止其他線程修改緩存
        readWriteLock.readLock().lock();
        try {
            String value = cache.get(key);
            // 如果緩存命中,返回
            if(value != null) {
                return value;
            }
        } finally {
            // 釋放讀鎖
            readWriteLock.readLock().unlock();
        }

        //如果緩存沒(méi)有命中,從數(shù)據(jù)庫(kù)中加載
        readWriteLock.writeLock().lock();
        try {
            // 細(xì)節(jié),為防止重復(fù)查詢數(shù)據(jù)庫(kù), 再次驗(yàn)證
            // 因?yàn)間et 方法上面部分是可能多個(gè)線程進(jìn)來(lái)的, 可能已經(jīng)向緩存填充了數(shù)據(jù)
            String value = cache.get(key);
            if(value == null) {
                // 這里可以改成從數(shù)據(jù)庫(kù)查詢
                value = "alvin";
                cache.put(key, value);
            }
            return value;
        } finally {
            readWriteLock.writeLock().unlock();
        }
    }

    // 更新數(shù)據(jù)
    public void updateData(String key, String value) {
        // 加寫鎖
        readWriteLock.writeLock().lock();
        try {
            // 更新操作TODO

            // 清空緩存
            cache.remove(key);
        } finally {
            readWriteLock.writeLock().unlock();
        }
    }
}
復(fù)制代碼
  • getData方法是讀取操作,先加讀鎖,從緩存讀取,如果沒(méi)有命中,加寫鎖,此時(shí)其他線程就不能讀取了,等寫入成功后,釋放讀鎖。
  • updateData方法是寫操作,更新時(shí)加寫鎖,其他線程此時(shí)無(wú)法讀取,然后清空緩存中的舊數(shù)據(jù)。

總結(jié)

本文講解了ReentrantReadWriteLock讀寫鎖常用的API, 以及通過(guò)幾個(gè)demo的演示,講解了讀寫鎖的使用,希望對(duì)大家有幫助。文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-463182.html

到了這里,關(guān)于通俗易懂讀寫鎖ReentrantReadWriteLock的使用的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來(lái)自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • useVModel()的使用------通俗易懂

    用于父子組件共享數(shù)據(jù), 1、父組件有個(gè)flag(Boolean)屬性 2、將flag屬性傳遞給子組件,要實(shí)現(xiàn)雙向數(shù)據(jù)綁定 3、flag屬性在子組件發(fā)生變化,父組件的flag屬性一起改變 父組件app.vue 1、父組件有flag屬性,使得flag和子組件uniInput雙向綁定 2、使用v-model:flag進(jìn)行雙向綁定,v-model的默

    2024年01月15日
    瀏覽(25)
  • python類(class)的定義、使用、繼承、應(yīng)用的通俗易懂理解

    1.為什么使用類 ????????一個(gè)類(class)可以包囊眾多函數(shù),所以一般使用類的情況下,都需要用到眾多有共性的函數(shù),把這些可能會(huì)一起調(diào)用的函數(shù)或者需要接連調(diào)用的函數(shù)歸為一個(gè)類,這樣需要使用的時(shí)候可以輕易的找到。 ????????在處理不同細(xì)節(jié)時(shí)使用的類區(qū)別

    2024年02月22日
    瀏覽(30)
  • 【通俗易懂】如何使用GitHub上傳文件,如何用git在github上傳文件

    【通俗易懂】如何使用GitHub上傳文件,如何用git在github上傳文件

    ? 目錄 創(chuàng)建 GitHub 倉(cāng)庫(kù) 使用 Git 進(jìn)行操作 步驟 1:初始化本地倉(cāng)庫(kù) 步驟 2:切換默認(rèn)分支 步驟 3:連接到遠(yuǎn)程倉(cāng)庫(kù) 步驟 4:獲取遠(yuǎn)程更改 步驟 5:添加文件到暫存區(qū) 步驟 6:提交更改 步驟 7:嘗試使用 SSH 協(xié)議 步驟 8:上傳項(xiàng)目 在現(xiàn)代軟件開發(fā)中,版本控制是一個(gè)至關(guān)重要的

    2024年02月12日
    瀏覽(19)
  • 【rpc】Dubbo和Zookeeper結(jié)合使用,它們的作用與聯(lián)系(通俗易懂,一文理解)

    目錄 Dubbo是什么?? ? ? ?? 把系統(tǒng)模塊變成分布式,有哪些好處,本來(lái)能在一臺(tái)機(jī)子上運(yùn)行,為什么還要遠(yuǎn)程調(diào)用 Zookeeper是什么? 它們進(jìn)行配合使用時(shí),之間的關(guān)系 服務(wù)注冊(cè) 服務(wù)發(fā)現(xiàn) 動(dòng)態(tài)地址管理 ????????Dubbo是一種開源的高性能、輕量級(jí)的分布式服務(wù)框架,它致力

    2024年02月09日
    瀏覽(16)
  • 用通俗易懂的方式講解大模型:Prompt 提示詞在開發(fā)中的使用

    用通俗易懂的方式講解大模型:Prompt 提示詞在開發(fā)中的使用

    OpenAI 的 ChatGPT 是一種領(lǐng)先的人工智能模型,它以其出色的語(yǔ)言理解和生成能力,為我們提供了一種全新的與機(jī)器交流的方式。但不是每個(gè)問(wèn)題都可以得到令人滿意的答案,如果想得到你所要的回答就要構(gòu)建好你的提示詞 Prompt。本文將探討 Prompt 提示詞在開發(fā)中的應(yīng)用和優(yōu)勢(shì),

    2024年02月03日
    瀏覽(21)
  • 深度學(xué)習(xí):使用nanodet訓(xùn)練自己制作的數(shù)據(jù)集并測(cè)試模型,通俗易懂,適合小白

    深度學(xué)習(xí):使用nanodet訓(xùn)練自己制作的數(shù)據(jù)集并測(cè)試模型,通俗易懂,適合小白

    關(guān)于目標(biāo)檢測(cè)的模型有很多, nanodet 模型小且輕量化,適合移植部署到硬件設(shè)備上,非常推薦學(xué)習(xí)這個(gè)模型。經(jīng)過(guò)我自己踩了無(wú)數(shù)坑后總結(jié)了此教程,助學(xué)剛接觸nanodet,想要快速上手的學(xué)者,教程很詳細(xì),學(xué)者耐心看。 我提供了一個(gè)已經(jīng)調(diào)試好的源碼包,后面的教程也都是

    2024年02月15日
    瀏覽(36)
  • Typescript - 通俗易懂的 interface 接口,創(chuàng)建接口 / 基礎(chǔ)使用 / 可選屬性 / 只讀屬性 / 任意屬性(詳細(xì)教程)

    在面向?qū)ο笳Z(yǔ)言中,接口是一個(gè)很重要的概念,它是對(duì)行為的抽象,而具體如何行動(dòng)需要由類去實(shí)現(xiàn)。 TypeScript 中的接口是一個(gè)非常靈活的概念,除了可用于 對(duì)類的一部分行為進(jìn)行抽象 以外,也常用于對(duì)「對(duì)象的形狀(Shape)」進(jìn)行描述。 ?TypeScript 的核心原則之一是對(duì)值所

    2023年04月15日
    瀏覽(27)
  • 用通俗易懂的方式講解:使用 LangChain 和 LlamaIndex 從零構(gòu)建PDF聊天機(jī)器人

    用通俗易懂的方式講解:使用 LangChain 和 LlamaIndex 從零構(gòu)建PDF聊天機(jī)器人

    隨著大型語(yǔ)言模型(LLM)(如ChatGPT和GPT-4)的興起,現(xiàn)在比以往任何時(shí)候都更容易搭建智能聊天機(jī)器人,并且可以堆積如山的文檔,為你的輸入提供更準(zhǔn)確的響應(yīng)。 無(wú)論你是想構(gòu)建個(gè)人助理、定制聊天機(jī)器人還是自動(dòng)文檔分析系統(tǒng),本系列都將為你提供構(gòu)建自己的LLM聊天機(jī)器

    2024年01月18日
    瀏覽(24)
  • 用通俗易懂的方式講解:使用 MongoDB 和 Langchain 構(gòu)建生成型AI聊天機(jī)器人

    用通俗易懂的方式講解:使用 MongoDB 和 Langchain 構(gòu)建生成型AI聊天機(jī)器人

    想象一下:你收到了你夢(mèng)寐以求的禮物:一臺(tái)非凡的時(shí)光機(jī),可以將你帶到任何地方、任何時(shí)候。 你只有10分鐘讓它運(yùn)行,否則它將消失。你擁有一份2000頁(yè)的PDF,詳細(xì)介紹了關(guān)于這臺(tái)時(shí)光機(jī)的一切:它的歷史、創(chuàng)造者、構(gòu)造細(xì)節(jié)、操作指南、過(guò)去的用戶,甚至還有一種回到過(guò)

    2024年01月23日
    瀏覽(26)
  • 用通俗易懂的方式講解:使用 Mistral-7B 和 Langchain 搭建基于PDF文件的聊天機(jī)器人

    用通俗易懂的方式講解:使用 Mistral-7B 和 Langchain 搭建基于PDF文件的聊天機(jī)器人

    在本文中,使用LangChain、HuggingFaceEmbeddings和HuggingFace的Mistral-7B LLM創(chuàng)建一個(gè)簡(jiǎn)單的Python程序,可以從任何pdf文件中回答問(wèn)題。 LangChain是一個(gè)在語(yǔ)言模型之上開發(fā)上下文感知應(yīng)用程序的框架。LangChain使用帶prompt和few-shot示例的LLM來(lái)提供相關(guān)響應(yīng)和推理。LangChain擅長(zhǎng)文檔問(wèn)答、聊天

    2024年01月24日
    瀏覽(27)

覺(jué)得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包