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

【六大鎖策略-各種鎖的對比-Java中的Synchronized鎖和ReentrantLock鎖的特點(diǎn)分析-以及加鎖的合適時機(jī)】

這篇具有很好參考價值的文章主要介紹了【六大鎖策略-各種鎖的對比-Java中的Synchronized鎖和ReentrantLock鎖的特點(diǎn)分析-以及加鎖的合適時機(jī)】。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點(diǎn)擊"舉報違法"按鈕提交疑問。

系列文章目錄



前言

閱讀該文章之前要了解,鎖策略是為了解決什么問題

多線程帶來的的風(fēng)險-線程安全的問題的簡單實(shí)例-線程不安全的原因


提示:以下是本篇文章正文內(nèi)容,下面案例可供參考

一、六大"有鎖策略"

鎖沖突是指兩個線程對一個對象加鎖,產(chǎn)生了阻塞等待。

1. 樂觀鎖——悲觀鎖

樂觀鎖

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

  • 預(yù)測接下來的鎖沖突不大(一般消耗的資源少,效率高點(diǎn))

悲觀鎖

  • 總是假設(shè)最壞的情況,每次去拿數(shù)據(jù)的時候都認(rèn)為別人會修改,所以每次在拿數(shù)據(jù)的時候都會上鎖,這樣別人想拿這個數(shù)據(jù)就會阻塞直到它拿到鎖。

  • 預(yù)測接下來的鎖沖突很大(一般消耗的資源多,效率低點(diǎn))


舉個例子

大學(xué)里的期末的最后一門考試結(jié)束后,當(dāng)天,輔導(dǎo)員就會通知假期就開始了,大家可以離校了。

  • 同學(xué)A樂觀鎖)認(rèn)為:反正,每次都是考試完,就可以直接走了,于是他就直接收拾行李,不等通知,直接當(dāng)時就回家了,出現(xiàn)意外再說。

  • 同學(xué)B悲觀鎖)認(rèn)為:萬一輔導(dǎo)員說這次放假延遲,大家都留校等領(lǐng)導(dǎo)通知,于是他就在宿舍一直等到輔導(dǎo)員通知,才開始收拾行李,出發(fā)回家。

此時,在B等待的時間里,A可能已經(jīng)到家了。(即A的回家效率高于B


2. 輕量級鎖——重量級鎖

該文中出現(xiàn)的“樂觀鎖”“偏向鎖”“等都會在后面介紹,讀者不必先理解,可先大致有個印象

輕量級鎖

  • 加鎖解鎖,過程更快更高效

  • 輕量級鎖在Java中是一種樂觀鎖的方式,使用CAS(比較和交換)實(shí)現(xiàn),它是通過在對象頭中標(biāo)記為“偏向鎖”來實(shí)現(xiàn)的。當(dāng)一個線程獲得該偏向鎖時,它就可以直接訪問被鎖定的對象,而不用執(zhí)行任何額外的同步操作。如果有其他線程來訪問該對象,輕量級鎖就會自動退化為重量級鎖。


重量級鎖

  • 加鎖解鎖,過程更慢更低效

  • 重量級鎖在Java中是一種悲觀鎖的方式,使用互斥鎖(Mutex Lock)實(shí)現(xiàn),它需要操作系統(tǒng)的支持。當(dāng)有多個線程同時訪問一個共享資源時,重量級鎖會把其他線程阻塞,直到當(dāng)前線程執(zhí)行完畢,釋放鎖。這種方式的效率較低,因為線程的上下文切換和系統(tǒng)調(diào)用開銷較大。

總結(jié)

  1. 輕量級鎖適用于競爭不激烈的情況,而重量級鎖適用于競爭激烈的情況。在實(shí)際開發(fā)中,我們需要根據(jù)具體場景選擇合適的鎖機(jī)制,以達(dá)到最佳的性能。

  2. 同時,樂觀鎖可能是輕量級鎖,悲觀鎖可能是重量級鎖(不絕對)


3. 自旋鎖——掛起等待鎖

自旋鎖

  • 一直占用CPU,不涉及線程阻塞和調(diào)度,持續(xù)不斷的請求鎖,一但鎖被釋放,就能立即得到,忙等
  • 如果其他線程一直不釋放鎖,那它就一直持續(xù)消耗CPU資源(該代碼通常是純用戶態(tài),不會設(shè)置很長的時間)

掛起等待鎖

  • 當(dāng)它發(fā)現(xiàn)沒有鎖的時候,就會進(jìn)入掛起等待狀態(tài)(掛機(jī)),掛起等待的時候是
    不消耗 CPU的

  • 它等待操作系統(tǒng)的通知喚醒,但是可能其他線程剛釋放了鎖,就被一直不斷請求的自旋鎖線程給槍走了,所以它只能繼續(xù)等待,具體拿到鎖的時機(jī),還得聽從操作系統(tǒng)的安排(該鎖一般是內(nèi)核機(jī)制,可能會等待較長的時間)

對照前文

  1. 自旋鎖是輕量級鎖的一種典型實(shí)現(xiàn)

  2. 掛起等待鎖是重量級鎖的一種典型實(shí)現(xiàn)


4. 互斥鎖——讀寫鎖

互斥鎖(例如:synchronized)

只有兩個操作:

  1. 進(jìn)入代碼塊,給該代碼塊加鎖。

  2. 出代碼塊,解鎖該帶代碼塊。

  3. 互斥鎖常用于保護(hù)共享數(shù)據(jù)結(jié)構(gòu)的訪問,如隊列、鏈表、散列表等。需要注意的是,互斥鎖使用不當(dāng)可能會帶來鎖競爭、死鎖等問題,

讀寫鎖(例如:ReentrantReadWriteLock)

  1. 給讀操作加鎖。(讀鎖,是一種共享鎖,可被多個線程同時擁有。當(dāng)讀鎖被占用時,其他讀鎖可以繼續(xù)被占用。共享性。)

  2. 給寫操作加鎖。(寫鎖,寫鎖是一種排他鎖,只能被一個線程占用,當(dāng)寫鎖被占用時,其他任何鎖都不能被占用。原子性。)

  3. 解鎖。

  4. 多個線程同時讀取一個變量,不會涉及到線程安全問題。讀寫鎖適用于對共享資源的讀操作頻繁,寫操作較少的情況,如高并發(fā)讀,比如緩存、數(shù)據(jù)維護(hù)等。讀寫鎖可以提高讀取效率,避免了互斥鎖的性能開銷。同時,寫操作的排他特性避免了并發(fā)寫操作對共享資源的影響,保證數(shù)據(jù)的正確性和一致性。

在讀鎖和寫鎖之間,約定:

  • 讀鎖和讀鎖之間,不會鎖競爭,不會產(chǎn)生阻塞等待。(不會影響執(zhí)行速度)

  • 寫鎖和寫鎖之間,有鎖競爭。(不會影響執(zhí)行速度)

  • 讀鎖和寫鎖之間,有鎖競爭。(會影響速度,但是保證線程安全)


5. 可重入鎖——不可重入鎖

可重入鎖,又名遞歸鎖(例如:synchronized)

  1. 如果一個鎖,在一個線程中,連續(xù)加鎖兩次,不死鎖,就叫做可重入鎖,死鎖了,就叫不可重入鎖。即允許同一個線程多次獲取同一把鎖,而不會產(chǎn)生死鎖。

  2. 這種鎖能夠保證同一線程多次訪問同一資源時不會發(fā)生沖突。

  3. Java里只要以Reentrant開頭命名的鎖都是可重入鎖,而且JDK提供的所有現(xiàn)成的Lock實(shí)現(xiàn)類,包括synchronized關(guān)鍵字鎖都是可重入的。

代碼示例

Object locker = new Object();
synchronized(locker) {
    synchronized(locker) {
        //連續(xù)加鎖兩次    
    }
}

//或者
//這也是兩次加鎖,針對this
class BlockingQueue {
    synchronized void put(int elem) {
        this.size();
    }
    
    synchronized int size() {}
}

不可重入鎖

  1. 同一線程第二次加鎖的時候, 會阻塞等待。直到第一次的鎖被釋放, 才能獲取到第二個鎖。 但是釋放第一個鎖也是由該線程來完成, 結(jié)果這個線程已經(jīng)阻塞了, 也就無法進(jìn)行解鎖操作.。這時候就會死鎖。

  2. 即在同一線程再次請求獲得該鎖時,會造成死鎖。因為該鎖只能被獲得一次,并且只有獲得鎖的線程才能釋放鎖。

  3. Linux系統(tǒng)提供的 mutex是不可重入鎖.


6. 公平鎖——非公平鎖

公平鎖

  1. 是指多個線程按照申請鎖的順序來獲取鎖,即先到先得的策略。(公不公平是由自己對公平的定義決定,Java中定義先到先得為公平,synchronized為非公平鎖,它遵循等概率競爭規(guī)則)

  2. 公平鎖的優(yōu)點(diǎn)是可以避免饑餓現(xiàn)象,即線程在獲取鎖時會受到先來先服務(wù)的原則,公平性是保證鎖最大程度分配給等待時間最長的線程,缺點(diǎn)是其效率較低,因為需要保存大量的線程狀態(tài)。

非公平鎖

  1. 多個線程獲取鎖的順序是不確定的,有可能后申請鎖的線程先獲取到鎖,這種方式可能造成某些線程一直無法獲取到鎖。

  2. 在Java中,ReentrantLock默認(rèn)就是非公平鎖。與公平鎖相比,非公平鎖調(diào)度的效率要高,但是不公平的分配策略可能會導(dǎo)致某些線程一直無法獲取到鎖,從而產(chǎn)生“饑餓”的現(xiàn)象。

  3. 在Java中,ReentrantLock默認(rèn)是非公平鎖,可以通過它的構(gòu)造函數(shù)改為公平鎖。


二、Synchronized——ReentrantLock

Synchronized的特點(diǎn)(JDK1.8)

  1. 開始時是樂觀鎖,如果鎖沖突頻繁,就轉(zhuǎn)換為悲觀鎖。

  2. 開始時輕量級鎖,如果鎖被持有時間較長,就轉(zhuǎn)換為重量級鎖。

  3. 輕量級鎖大概率基于自旋實(shí)現(xiàn),重量級鎖大概率基于掛起等待實(shí)現(xiàn)。

  4. 不是讀寫鎖。

  5. 是可重入鎖。

  6. 是非公平鎖。

Synchronized的鎖升級策略

都是盡可能減少鎖帶來的的開銷

【六大鎖策略-各種鎖的對比-Java中的Synchronized鎖和ReentrantLock鎖的特點(diǎn)分析-以及加鎖的合適時機(jī)】,java,開發(fā)語言,java-ee,后端

  • 無鎖

  • 偏向鎖(非必要不加鎖

即線程對鎖有個標(biāo)記,沒有競爭就不加鎖,倘若有別的線程競爭,就立即加鎖,即高效又安全

  • 自旋鎖 / 輕量級鎖(遇到了鎖競爭,但是目前線程較少,就讓它自旋一會,說不定很快就拿到了 )

  • 重量級鎖(線程競爭激烈,多個線程都在自旋,大量占用cpu資源,直接升級鎖,調(diào)用系統(tǒng)內(nèi)核阻塞等待)

主流的JVM只能鎖升級,不能降級,不是實(shí)現(xiàn)不了,可能需要付出更大的代價,于是干脆就不降級了

ReentrantLock的特點(diǎn)

  1. 可重入:同一個線程可以多次獲取鎖,避免了死鎖的發(fā)生。

  2. 公平鎖和非公平鎖:ReentrantLock可以通過參數(shù)指定是公平鎖還是非公平鎖。

  3. 條件變量:ReentrantLock可以通過維護(hù)條件變量來實(shí)現(xiàn)線程間的協(xié)調(diào)。

  4. 中斷響應(yīng):ReentrantLock支持線程中斷,即在等待鎖的過程中,可以響應(yīng)中斷信號。

  5. 限時等待:ReentrantLock支持線程等待一定時間,如果在指定時間內(nèi)還未獲取到鎖,就會放棄等待。

Synchronized和ReentranLock對比

  1. ReentranLock是可重入鎖,提供lock()unlock()獨(dú)立方法(即需要手動釋放),來進(jìn)行加鎖解鎖,synchronized也是可重入鎖(基于代碼塊的方式來控制加鎖解鎖),它在第二次加鎖之前,會判定當(dāng)前鎖的擁有者是否是同一個線程,如果是,則直接放行,不必再加一次鎖

  2. synchronized是非公平的,若想要公平,需要手動加個優(yōu)先級隊列來記錄順序。ReentrantLock提供公平和非公平兩種工作模式,默認(rèn)是非公平鎖, 在構(gòu)造方法中傳入true,開啟公平鎖。

  3. synchronized搭配Objectwaitnotify進(jìn)行等待喚醒,如果多個線程wait()同一個對象,notify()隨機(jī)喚醒一個。ReentrantLock需要搭配Condition這個類,這個類也能起到等待通知的作用,能夠精準(zhǔn)喚醒某個線程, 功能更強(qiáng)大。

  4. synchronized是一個關(guān)鍵字, 是 JVM內(nèi)部實(shí)現(xiàn)的(大概率是基于 C++ 實(shí)現(xiàn)). ReentrantLock是標(biāo)準(zhǔn)庫的一個類, 在 JVM 外實(shí)現(xiàn)的(基于Java實(shí)現(xiàn))

  5. synchronized在申請鎖失敗時, 會死等. ReentrantLock可以通過 trylock()的方式等待一段時間就放棄, 不會阻塞,而是返回false(讓用戶自己決定后續(xù)操作)。

三、鎖消除——鎖粗化

鎖消除

  • 非必要不加鎖(不濫用synchronized)

  • 編譯器+JVM就會會作出優(yōu)化,檢測當(dāng)前代碼是否是多線程執(zhí)行 / 是否有必要加鎖,如果沒必要,就自動把鎖去掉。

例如:StringBuilder和StringBuffer,后者帶鎖,但是如果單線程使用后者,就自動將后者優(yōu)化為前者。(該手段十分保守,只有保證消除是可靠的,才會啟動,寧愿什么也不做,也不愿意犯錯

鎖粗化

【六大鎖策略-各種鎖的對比-Java中的Synchronized鎖和ReentrantLock鎖的特點(diǎn)分析-以及加鎖的合適時機(jī)】,java,開發(fā)語言,java-ee,后端

  • 鎖的粒度,synchronized代碼塊,包含代碼的多少(代碼越多,粒度越粗。代碼越少,粒度越細(xì))

  • 一般寫代碼,多數(shù)情況下,希望粒度小一些。(串行執(zhí)行的代碼少,并發(fā)執(zhí)行的代碼多)但是如果某個場景,頻繁的加鎖/解鎖,此時編譯器就會把它優(yōu)化為一個更粗粒度的鎖。文章來源地址http://www.zghlxwxcb.cn/news/detail-615012.html

到了這里,關(guān)于【六大鎖策略-各種鎖的對比-Java中的Synchronized鎖和ReentrantLock鎖的特點(diǎn)分析-以及加鎖的合適時機(jī)】的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

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

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

相關(guān)文章

  • synchronized各種使用場景

    開啟10個線程,每個線程中循環(huán)100次對result變量進(jìn)行++自增,主線程等待10s后輸出result值結(jié)果 結(jié)果 執(zhí)行結(jié)果不一定是869,可能是其他的數(shù),總之就是比正確的結(jié)果1000小 原因 result++這個操作的執(zhí)行過程其實(shí)是3個步驟 讀取result變量 將result變量進(jìn)行+1 將result值再賦給result變量 詳

    2023年04月23日
    瀏覽(35)
  • JUC并發(fā)編程(終章)各種鎖的理解

    JUC并發(fā)編程(終章)各種鎖的理解

    公平鎖、非公平鎖 公平鎖:先到先得(不可插隊) 非公平鎖:達(dá)者為先(可插隊)----------默認(rèn) 可重入鎖(遞歸鎖) 所有的鎖都是可重入鎖 Synchronized版 ems方法中包含了call方法,所以當(dāng)我們調(diào)用ems方法獲取到鎖時,也把call方法的synchronized鎖獲取到了。 錯誤理論 當(dāng)線程A運(yùn)行

    2024年02月05日
    瀏覽(40)
  • 【JavaEE】鎖的策略

    【JavaEE】鎖的策略

    作者主頁: paper jie_博客 本文作者:大家好,我是paper jie,感謝你閱讀本文,歡迎一建三連哦。 本文于《JavaEE》專欄,本專欄是針對于大學(xué)生,編程小白精心打造的。筆者用重金(時間和精力)打造,將基礎(chǔ)知識一網(wǎng)打盡,希望可以幫到讀者們哦。 其他專欄:《MySQL》《C語言》

    2024年02月04日
    瀏覽(19)
  • Nginx配置大全【六大使用場景、七大負(fù)載均衡策略、四大負(fù)載健康檢查】

    !!! 反向代理也可以基于請求路徑轉(zhuǎn)發(fā)到不同服務(wù)器 !!! !!!反向代理路徑結(jié)尾加不加 / 符號的區(qū)別?。?! 如果只是簡單的重定向操作,并且不需要進(jìn)行復(fù)雜的路徑重寫或捕獲,推薦使用 return 301 的方式來實(shí)現(xiàn)重定向。這樣能夠更直接、更高效地達(dá)到重定向的目的,避免不必要的

    2024年04月16日
    瀏覽(20)
  • Java 中的各種鎖

    對于線程是否需要鎖住共享的資源,我們可以將其分為樂觀鎖與悲觀鎖,前者不會鎖住共享資源后者會將共享資源進(jìn)行鎖住。 樂觀鎖是一種樂觀思想,即認(rèn)為讀多寫少,遇到并發(fā)寫的可能性低,每次去拿數(shù)據(jù)的時候都認(rèn)為別人不會修改,所以不會上鎖,但是在更新時會判斷此

    2024年02月03日
    瀏覽(16)
  • 【JavaEE初階】多線程進(jìn)階(五)常見鎖策略 CAS synchronized優(yōu)化原理

    【JavaEE初階】多線程進(jìn)階(五)常見鎖策略 CAS synchronized優(yōu)化原理

    樂觀鎖:預(yù)測鎖競爭不是很激烈。 悲觀鎖:預(yù)測鎖競爭會很激烈。 以上定義并不是絕對的,具體看預(yù)測鎖競爭激烈程度的結(jié)論。 輕量級鎖加鎖解鎖開銷比較小,效率更高。 重量級鎖加鎖解鎖開銷比較大,效率更低。 多數(shù)情況下,樂觀鎖也是一個輕量級鎖。 多數(shù)情況下,悲

    2024年02月03日
    瀏覽(31)
  • JAVA中的各種循環(huán)語句

    目錄 一、if循環(huán) 二、if與else if循環(huán)的運(yùn)用 三、while循環(huán) 四、for循環(huán) 我下面都用案例來解釋和展示循環(huán),大家結(jié)合案例和注釋多加感悟,將會對Java循環(huán)有個不錯了解。 ? 下面為一個輸入成績判定情況 if與else if同時使用可以篩選多個條件。最后一個else可以篩選以上不滿足的情

    2023年04月08日
    瀏覽(18)
  • Redis實(shí)戰(zhàn)案例14-分布式鎖的基本原理、不同實(shí)現(xiàn)方法對比以及基于Redis進(jìn)行實(shí)現(xiàn)思路

    Redis實(shí)戰(zhàn)案例14-分布式鎖的基本原理、不同實(shí)現(xiàn)方法對比以及基于Redis進(jìn)行實(shí)現(xiàn)思路

    基于數(shù)據(jù)庫的分布式鎖:這種方式使用數(shù)據(jù)庫的特性來實(shí)現(xiàn)分布式鎖。具體流程如下: 獲取鎖:當(dāng)一個節(jié)點(diǎn)需要獲得鎖時,它嘗試在數(shù)據(jù)庫中插入一個特定的唯一鍵值(如唯一約束的主鍵),如果插入成功,則表示獲得了鎖。 釋放鎖:當(dāng)節(jié)點(diǎn)完成任務(wù)后,通過刪除該唯一鍵

    2024年02月13日
    瀏覽(49)
  • Java中的各種引用類型以及部分引用的相關(guān)例子

    Java中的各種引用類型以及部分引用的相關(guān)例子

    在Java中,引用類型主要有四種,分別是:強(qiáng)引用(Strong Reference)、軟引用(Soft Reference)、弱引用(Weak Reference)和虛引用(Phantom Reference)。這些類型通常與垃圾回收機(jī)制有關(guān),用來描述對象的生命周期和可達(dá)性。下面詳細(xì)介紹每一種引用類型: 強(qiáng)引用 (Strong Reference) 強(qiáng)

    2024年04月13日
    瀏覽(17)
  • 一文全覽各種 ES 查詢在 Java 中的實(shí)現(xiàn)

    一文全覽各種 ES 查詢在 Java 中的實(shí)現(xiàn)

    以下為摘錄自用,非本人撰寫 本文基于elasticsearch 7.13.2版本,es從7.0以后,發(fā)生了很大的更新。7.3以后,已經(jīng)不推薦使用TransportClient這個client,取而代之的是Java High Level REST Client。 首先是,Mysql中的部分測試數(shù)據(jù): Mysql中的一行數(shù)據(jù)在ES中以一個文檔形式存在: 簡單梳理了一

    2024年02月11日
    瀏覽(16)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

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

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包