最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java多線程中常見(jiàn)的鎖策略詳解

 更新時(shí)間:2023年07月20日 11:23:32   作者:一只愛(ài)打拳的程序猿  
這篇文章主要介紹了Java多線程中常見(jiàn)的鎖策略詳解,在Java多線程中鎖(synchronized)也會(huì)根據(jù)鎖的競(jìng)爭(zhēng)程度來(lái)升級(jí)為相關(guān)“高等級(jí)”鎖,本文為了更好的理解?synchronized?加鎖機(jī)制,對(duì)其做出了詳細(xì)解釋,需要的朋友可以參考下

1. 悲觀鎖與樂(lè)觀鎖

悲觀鎖:為了保證原子性,因此把數(shù)據(jù)進(jìn)行上鎖,每一個(gè)不同的線程拿數(shù)據(jù)的時(shí)候都會(huì)參與鎖的競(jìng)爭(zhēng),其他線程想必須等待前者拿完數(shù)據(jù)解鎖后才能參與拿數(shù)據(jù)。

舉例,由于維修導(dǎo)致一層樓只剩下一間廁所。因此,線程1進(jìn)入廁所后,其他線程只能阻塞等待。

樂(lè)觀鎖:假設(shè)數(shù)據(jù)一般情況下不會(huì)產(chǎn)生并發(fā)沖突,所以在數(shù)據(jù)進(jìn)行提交更新的時(shí)候,才會(huì)正式對(duì)數(shù)據(jù)是否產(chǎn)生并發(fā)沖突進(jìn)行檢測(cè),如果發(fā)現(xiàn)并發(fā)沖突了,則讓返回用戶錯(cuò)誤的信息,讓用戶決定如何去做。

還是上述上廁所例子,線程1 給其他線返回一個(gè)信息,其他線程可根據(jù)信息選擇換樓層上廁所亦或是等待。

以上的上廁所例子,在樓棟廁所不充足情況下。線程還是盲目選擇這棟樓的廁所(使用悲觀鎖)就會(huì)導(dǎo)致阻塞消耗系統(tǒng)資源。在樓棟廁所充足的情況下,線程選擇了這棟樓的廁所(使用樂(lè)觀鎖)這樣就能很好的利用系統(tǒng)資源。

synchronized 初始情況下使用的是樂(lè)觀鎖,當(dāng)發(fā)現(xiàn)鎖競(jìng)爭(zhēng)激烈時(shí)候就會(huì)自動(dòng)轉(zhuǎn)換為悲觀鎖。就好比一個(gè)線程去某一棟樓上廁所,并不知道該樓棟是否廁所充足。充足就不阻塞等待,不充足就阻塞等待。

2. 讀寫(xiě)鎖與互斥鎖

多線程中,線程作為讀取方不會(huì)產(chǎn)生線程安全問(wèn)題,當(dāng)線程作為為寫(xiě)入方和線程作為寫(xiě)入方之間進(jìn)行交互和,線程作為寫(xiě)入方和線程作為讀取方之間進(jìn)行交互,就會(huì)造成互斥。

線程對(duì)數(shù)據(jù)的訪問(wèn),主要存在三種情況:

  • 線程只是對(duì)數(shù)據(jù)進(jìn)行讀操作,此時(shí)自然不會(huì)出現(xiàn)線程不安全問(wèn)題。
  • 多個(gè)線程對(duì)數(shù)據(jù)進(jìn)行寫(xiě)操作,就會(huì)出現(xiàn)線程不安全問(wèn)題。
  • 一個(gè)線程對(duì)數(shù)據(jù)進(jìn)行讀操作,另個(gè)線程對(duì)數(shù)據(jù)進(jìn)行寫(xiě)操作,也會(huì)出現(xiàn)線程不安全問(wèn)題。

簡(jiǎn)單的來(lái)說(shuō),線程的讀操作,就是線程對(duì)數(shù)據(jù)進(jìn)行訪問(wèn)。線程的寫(xiě)操作,就是線程對(duì)數(shù)據(jù)進(jìn)行修改。讀一下問(wèn)題不大,但寫(xiě)一下就難免會(huì)造成意外。因此,我們有了 讀寫(xiě)鎖 這個(gè)概念。

讀寫(xiě)鎖,就是把讀和寫(xiě)這兩個(gè)操作分開(kāi)來(lái)加鎖這樣就能避免互斥。Java 標(biāo)準(zhǔn)庫(kù)提供了一個(gè) ReentrantReadWriteLock 類(lèi),實(shí)現(xiàn)了讀寫(xiě)鎖。

ReentrantReadWriteLock.ReadLock 類(lèi)表示一個(gè)讀鎖.。這個(gè)對(duì)象提供了 lock / unlock 方法進(jìn)行加鎖解鎖。

ReentrantReadWriteLock.WriteLock 類(lèi)表示一個(gè)寫(xiě)鎖.。這個(gè)對(duì)象也提供了 lock / unlock 方法進(jìn)行加鎖解鎖。

  • 讀加鎖與讀加鎖之間,不互斥
  • 寫(xiě)加鎖與寫(xiě)加鎖之間,互斥
  • 讀加鎖與寫(xiě)加鎖之間,互斥

互斥,就會(huì)操作線程的掛起等待,一旦線程掛起等待了,就不知道什么時(shí)候能夠被喚醒了。因此,我們?cè)诰帉?xiě)代碼的時(shí)候盡可能減少互斥。

讀寫(xiě)鎖特別適用于“頻繁讀,不頻繁寫(xiě)”的場(chǎng)景中。比如,學(xué)校的教務(wù)系統(tǒng):

假設(shè)計(jì)算機(jī)軟件專(zhuān)業(yè)的學(xué)生有 300 個(gè)同學(xué),這300個(gè)同學(xué)幾乎每天都要課程表為了防止課表更改,這樣的一個(gè)操作就是頻繁讀(訪問(wèn))。

有特殊情況,老師生病了或是怎樣,偶爾會(huì)調(diào)課到其他時(shí)間點(diǎn)。這樣的操作,就是不頻繁寫(xiě)(修改)。

注意,synchronized 不是讀寫(xiě)鎖。

3. 重量級(jí)鎖與輕量級(jí)鎖

在并發(fā)編程中,輕量級(jí)鎖和重量級(jí)鎖是兩種鎖的實(shí)現(xiàn)方法,主要用于解決多個(gè)線程同時(shí)訪問(wèn)共享資源時(shí)的同步問(wèn)題。

輕量級(jí)鎖通常用于鎖競(jìng)爭(zhēng)不激烈的情況下,通過(guò)在線程內(nèi)部使用CAS操作來(lái)進(jìn)行加鎖和解鎖,這種方式不需要進(jìn)行線程的上下文切換,因此性能比重量級(jí)鎖更高。但是,如果鎖競(jìng)爭(zhēng)激烈的話,輕量級(jí)鎖的性能優(yōu)勢(shì)就不明顯了。

重量級(jí)鎖通常用于鎖競(jìng)爭(zhēng)激烈的情況下,通過(guò)將競(jìng)爭(zhēng)鎖的線程掛起并切換到內(nèi)核態(tài)來(lái)進(jìn)行加鎖和解鎖。由于需要進(jìn)行線程的上下文切換,因此性能比輕量級(jí)鎖更低。但是,在鎖競(jìng)爭(zhēng)激烈的情況下,重量級(jí)鎖的效果要比輕量級(jí)鎖好得多,因?yàn)樗梢杂行У乇苊怄i爭(zhēng)用問(wèn)題,減少了線程的搶占和切換,從而提高了系統(tǒng)的效率和響應(yīng)速度。

synchronized 的輕量級(jí)鎖策略大概都是通過(guò)自旋鎖的方式實(shí)現(xiàn)的,重量級(jí)鎖則是掛起等待鎖。

4. 自旋鎖與掛起等待鎖

自旋鎖 VS 掛起等待鎖:

自旋鎖,當(dāng)線程之間進(jìn)行搶占鎖內(nèi)資源時(shí)候,線程1 已經(jīng)搶占到鎖,線程2 則會(huì)持續(xù)等待 線程1 鎖內(nèi)任務(wù)結(jié)束后再進(jìn)行搶占鎖資源,在這期間 線程2 持續(xù)處于阻塞等待狀態(tài)。

掛起等待鎖,當(dāng)掛起等待鎖遇到這種情況時(shí),發(fā)現(xiàn)有線程已經(jīng)搶占到鎖了,則會(huì)放棄阻塞等待。直到鎖開(kāi)放了,則再參與搶占鎖。

因此,自旋鎖有以下優(yōu)缺點(diǎn):

  • 優(yōu)點(diǎn):時(shí)刻占用系統(tǒng)資源,不涉及線程阻塞和調(diào)度,一旦鎖被釋放了,參與鎖的競(jìng)爭(zhēng)。
  • 缺點(diǎn):當(dāng)鎖內(nèi)任務(wù)比較復(fù)雜時(shí),鎖被其他線程占有時(shí)間過(guò)長(zhǎng),那么就會(huì)持續(xù)消耗系統(tǒng)資源。
  • 掛起等待鎖則相反

4.1 自旋鎖

自旋鎖,按照正常的邏輯,當(dāng)線程搶占鎖時(shí)進(jìn)入阻塞狀態(tài),過(guò)不了多久鎖就被釋放了。因此,自旋鎖就沒(méi)必要放棄 CPU 了,一直占用著 CPU 的內(nèi)存空間。

自旋鎖偽代碼:

while(槍鎖lock == 失敗) {}

如果獲取鎖失敗,立即再嘗試獲取鎖,無(wú)限循環(huán)下去直到獲取到鎖為止。第一次獲取鎖失敗,往后的獲取鎖操作會(huì)在極短的時(shí)間內(nèi)到來(lái),一旦鎖被其他線程釋放,就能第一時(shí)間獲取到鎖。這就是輕量級(jí)鎖的體現(xiàn)(鎖的競(jìng)爭(zhēng)還不太激烈,嘗試使用自旋方式加鎖)。

4.2 掛起等待鎖

當(dāng)線程獲取鎖失敗后,并不會(huì)進(jìn)行阻塞等待。而隨著系統(tǒng)的調(diào)度,不占用 CPU 。直到鎖開(kāi)發(fā)后,再嘗試參與鎖競(jìng)爭(zhēng)。這種情況就是掛起等待鎖,也是重量級(jí)鎖的體現(xiàn)(鎖的競(jìng)爭(zhēng)太激烈了,線程跟隨系統(tǒng)的調(diào)度)。

舉例:

自旋鎖與掛起等待鎖的現(xiàn)實(shí)生活體現(xiàn):張三是一個(gè)普通的男生,如花是一個(gè)漂亮的女孩,在此張三作為線程,如花作為鎖。

張三開(kāi)始追求如花,但是如花已經(jīng)有男朋友了。張三又是個(gè)死皮賴臉的人。每天堅(jiān)持給女孩發(fā)信息,期待著某一天如花分手,能得到如花。此時(shí)張三就處于自旋鎖的狀態(tài)。

隨著競(jìng)爭(zhēng)的激烈,又有許多人想要追求如花。張三開(kāi)始動(dòng)搖了,開(kāi)始努力敲代碼、認(rèn)真學(xué)習(xí)不參與追如花的競(jìng)爭(zhēng)了(隨著系統(tǒng)的調(diào)度做其他事去了)。如果某一天如花變?yōu)閱紊砹?,系統(tǒng)會(huì)通知張三如花單身了(鎖空閑了),張三就又開(kāi)始參與競(jìng)爭(zhēng)鎖。此時(shí)張三的狀態(tài)就是掛起等待鎖狀態(tài)。

5. 公平鎖與非公平鎖

公平鎖與非公平鎖講究四個(gè)字“公平競(jìng)爭(zhēng)”,假設(shè)有三個(gè)線程搶占鎖資源,當(dāng)鎖被釋放后就會(huì)出現(xiàn)兩種情況:公平競(jìng)爭(zhēng)鎖、非公平競(jìng)爭(zhēng)鎖。

公平鎖:遵循先來(lái)后到的原則,線程1 進(jìn)入鎖,鎖釋放后。線程2 進(jìn)入鎖,鎖再釋放后。線程3 進(jìn)入鎖。整個(gè)過(guò)程是按照順序執(zhí)行的。

非公平鎖:由于線程之間搶占資源,導(dǎo)致鎖被無(wú)序的搶占。這樣 3 個(gè)線程都有機(jī)會(huì)優(yōu)先進(jìn)入鎖。整個(gè)過(guò)程會(huì)造成無(wú)序執(zhí)行。

通過(guò)上圖我們就能很好的理解,公平鎖與非公平鎖之間的差異。當(dāng)然,線程的調(diào)度是隨機(jī)的因此多個(gè)線程競(jìng)爭(zhēng)鎖時(shí)可以隨意進(jìn)行搶占“手快有,手慢無(wú)”(非公平鎖)。要想實(shí)現(xiàn)公平鎖,我們可以使用一些特定的數(shù)據(jù)結(jié)構(gòu)來(lái)達(dá)到按順序使用鎖。

在實(shí)際開(kāi)發(fā)中,公平鎖與非公平鎖沒(méi)有好壞之分,我們按照需求來(lái)進(jìn)行設(shè)置。注意,synchronized 屬于非公平鎖。

6. 可重入鎖與不可重入鎖

可重入鎖即允許一個(gè)線程多次獲取同一把鎖。

不可重入鎖是指一旦線程獲得了該鎖,此時(shí)再次請(qǐng)求獲取該鎖時(shí),系統(tǒng)會(huì)將該線程掛起,直到該鎖被釋放為止。因此,不可重入鎖不能再同一線程中重復(fù)獲取。

可重入鎖是指當(dāng)一個(gè)線程獲得了該鎖之后,在該鎖還未釋放之前,可以再次獲取該鎖。這種鎖可以防止死鎖的發(fā)生,因?yàn)樵讷@取之后可以在方法中重新獲取該鎖,從而避免死鎖的發(fā)生。

Java 中的 synchronized 關(guān)鍵字是一種可重入鎖,而 ReentrantLock 是 Java 中常用的可重入鎖類(lèi),synchronized 不需要手動(dòng)解鎖,而 ReentrantLock 需要手動(dòng)解鎖。

需要注意的是,可重入鎖雖然提高了代碼的靈活性和可維護(hù)性,但同時(shí)也可能會(huì)帶來(lái)出現(xiàn)深度嵌套鎖的風(fēng)險(xiǎn),引發(fā)死鎖或性能下降等問(wèn)題。因此,在使用可重入鎖時(shí)需要仔細(xì)設(shè)計(jì)和管理。

談?wù)勀銓?duì)synchronized的演變過(guò)程的理解?

synchronized 既是悲觀鎖也是樂(lè)觀鎖,synchronized 即是輕量級(jí)鎖也是重量級(jí)鎖,synchronized 即是自旋鎖也是掛起等待鎖,synchronized 不是讀寫(xiě)鎖,synchronized 是非公平鎖,synchronized是可重入鎖。

synchronized 的初始化的時(shí)候是一個(gè)樂(lè)觀鎖/輕量級(jí)鎖/自旋鎖,隨著synchronized的競(jìng)爭(zhēng)激烈會(huì)升級(jí)為悲觀鎖/重量級(jí)鎖/掛起等待鎖,另外輕量級(jí)鎖是部分基于自旋鎖、重量級(jí)鎖是部分基于掛起等待鎖。

在鎖的策略中還會(huì)引申到“死鎖”的概念,在下篇博文中,我會(huì)介紹。大家也可以通過(guò)下方專(zhuān)欄中搜索多線程相關(guān)內(nèi)容。

到此這篇關(guān)于Java多線程中常見(jiàn)的鎖策略詳解的文章就介紹到這了,更多相關(guān)Java常見(jiàn)的鎖策略內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Java中實(shí)現(xiàn)Comparator接口和用法實(shí)例(簡(jiǎn)明易懂)

    Java中實(shí)現(xiàn)Comparator接口和用法實(shí)例(簡(jiǎn)明易懂)

    這篇文章主要介紹了Java中實(shí)現(xiàn)Comparator接口和用法實(shí)例(簡(jiǎn)明易懂),本文給出實(shí)現(xiàn)Comparator接口的實(shí)例和使用這個(gè)接口的代碼實(shí)例,需要的朋友可以參考下
    2015-05-05
  • JAVA多線程實(shí)現(xiàn)的四種方式及使用場(chǎng)景詳解

    JAVA多線程實(shí)現(xiàn)的四種方式及使用場(chǎng)景詳解

    這篇文章主要介紹了JAVA多線程實(shí)現(xiàn)的四種方式及使用場(chǎng)景,并舉例說(shuō)明了在管理系統(tǒng)中多線程的應(yīng)用場(chǎng)景,如數(shù)據(jù)導(dǎo)入導(dǎo)出、數(shù)據(jù)緩存更新、并發(fā)用戶操作處理、系統(tǒng)監(jiān)控和定時(shí)任務(wù)執(zhí)行,需要的朋友可以參考下
    2025-01-01
  • mybatis-generator 修改表結(jié)構(gòu)后實(shí)體不更新問(wèn)題及解決方法

    mybatis-generator 修改表結(jié)構(gòu)后實(shí)體不更新問(wèn)題及解決方法

    本文主要介紹了如何在MyBatis Generator中修改表結(jié)構(gòu)后更新實(shí)體類(lèi)的問(wèn)題,并提供了解決方案,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧
    2025-04-04
  • @Autowired注解以及失效的幾個(gè)原因圖文詳解

    @Autowired注解以及失效的幾個(gè)原因圖文詳解

    在微服務(wù)項(xiàng)目中,會(huì)遇到@Autowired注解失效的情況,下面這篇文章主要給大家介紹了關(guān)于@Autowired注解以及失效的幾個(gè)原因的相關(guān)資料,文中通過(guò)圖文介紹的非常詳細(xì),需要的朋友可以參考下
    2023-03-03
  • 在springboot中如何集成clickhouse進(jìn)行讀寫(xiě)操作

    在springboot中如何集成clickhouse進(jìn)行讀寫(xiě)操作

    本文介紹了在Spring Boot中集成ClickHouse的步驟,包括引入依賴、配置數(shù)據(jù)源、編寫(xiě)實(shí)體類(lèi)和Mapper類(lèi)進(jìn)行CRUD操作,特別提到批量插入時(shí)需要在SQL語(yǔ)句中添加`FORMAT`以避免錯(cuò)誤,在實(shí)際應(yīng)用中,與MySQL的操作類(lèi)似,只需將ClickHouse當(dāng)作MySQL使用
    2024-11-11
  • java中this關(guān)鍵字的詳細(xì)使用介紹

    java中this關(guān)鍵字的詳細(xì)使用介紹

    大家好,本篇文章主要講的是java中this關(guān)鍵字的詳細(xì)使用介紹,感興趣的同學(xué)趕快來(lái)看一看吧,對(duì)你有幫助的話記得收藏一下,方便下次瀏覽
    2022-01-01
  • IntelliJ?IDEA中如何使用Checkstyle對(duì)Java代碼規(guī)范檢查

    IntelliJ?IDEA中如何使用Checkstyle對(duì)Java代碼規(guī)范檢查

    這篇文章主要介紹了IntelliJ IDEA中如何使用Checkstyle對(duì)Java代碼規(guī)范檢查的相關(guān)資料,checkstyle是提高代碼質(zhì)量,檢查代碼規(guī)范的很好用的一款工具,文中通過(guò)代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2026-03-03
  • Java的MyBatis框架項(xiàng)目搭建與hellow world示例

    Java的MyBatis框架項(xiàng)目搭建與hellow world示例

    MyBatis框架為Java程序的數(shù)據(jù)庫(kù)操作帶來(lái)了很大的便利,這里我們就從最基礎(chǔ)的入手,來(lái)看一下Java的MyBatis框架項(xiàng)目搭建與hellow world示例,需要的朋友可以參考下
    2016-06-06
  • Java深拷貝與淺拷貝全維度解析(含面試?/?筆試?+?實(shí)戰(zhàn))

    Java深拷貝與淺拷貝全維度解析(含面試?/?筆試?+?實(shí)戰(zhàn))

    在Java中深拷貝與淺拷貝是對(duì)象復(fù)制的兩種方式,它們的主要區(qū)別在于對(duì)對(duì)象中引用類(lèi)型字段的處理方式,這篇文章主要介紹了Java深拷貝與淺拷貝全維度解析的相關(guān)資料,文中通過(guò)代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2026-01-01
  • springboot 項(xiàng)目容器啟動(dòng)后如何自動(dòng)執(zhí)行指定方法

    springboot 項(xiàng)目容器啟動(dòng)后如何自動(dòng)執(zhí)行指定方法

    這篇文章主要介紹了springboot 項(xiàng)目容器啟動(dòng)后如何自動(dòng)執(zhí)行指定方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-11-11

最新評(píng)論

密云县| 平凉市| 罗田县| 罗定市| 赤壁市| 雷山县| 开化县| 库车县| 保亭| 汉寿县| 绥棱县| 呼玛县| 遂昌县| 乐陵市| 安多县| 汽车| 镇平县| 松原市| 金寨县| 宁武县| 岳西县| 宁都县| 玉田县| 敖汉旗| 陆良县| 凤台县| 阿克苏市| 舟山市| 喀什市| 乐山市| 通山县| 武乡县| 崇阳县| 门源| 驻马店市| 天津市| 交城县| 上思县| 浮梁县| 虞城县| 汕头市|