欧美一区二区三区老妇人-欧美做爰猛烈大尺度电-99久久夜色精品国产亚洲a-亚洲福利视频一区二区

java并發(fā)編程中悲觀鎖和樂觀鎖是什么意思

這篇文章主要介紹java并發(fā)編程中悲觀鎖和樂觀鎖是什么意思,文中介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們一定要看完!

創(chuàng)新互聯(lián)服務(wù)緊隨時代發(fā)展步伐,進(jìn)行技術(shù)革新和技術(shù)進(jìn)步,經(jīng)過十余年的發(fā)展和積累,已經(jīng)匯集了一批資深網(wǎng)站策劃師、設(shè)計(jì)師、專業(yè)的網(wǎng)站實(shí)施團(tuán)隊(duì)以及高素質(zhì)售后服務(wù)人員,并且完全形成了一套成熟的業(yè)務(wù)流程,能夠完全依照客戶要求對網(wǎng)站進(jìn)行成都網(wǎng)站設(shè)計(jì)、做網(wǎng)站、建設(shè)、維護(hù)、更新和改版,實(shí)現(xiàn)客戶網(wǎng)站對外宣傳展示的首要目的,并為客戶企業(yè)品牌互聯(lián)網(wǎng)化提供全面的解決方案。

悲觀鎖

悲觀鎖是平時開發(fā)中經(jīng)常用到的一種鎖,比如ReentrantLocksynchronized等就是這種思想的體現(xiàn),它總是假設(shè)別的線程在拿線程的時候都會修改數(shù)據(jù),所以每次拿到數(shù)據(jù)的時候都會上鎖,這樣別的線程想拿這個數(shù)據(jù)就會被阻塞。如圖所示:

java并發(fā)編程中悲觀鎖和樂觀鎖是什么意思  

synchronized是悲觀鎖的一種實(shí)現(xiàn),一般我們都會有這樣使用:

private static Object monitor = new Object();

public static void main(String[] args) throws Exception {
    //鎖一段代碼塊
    synchronized (monitor){

    }
}
//鎖實(shí)例方法,鎖對象是this,即該類實(shí)例本身
public synchronized void doSome(){

}
//鎖靜態(tài)方法,鎖對象是該類,即XXX.class
public synchronized static void add(){

}
 

我們以最簡單的同步代碼塊來分析,其實(shí)就是將synchronized作用于一個給定的實(shí)例對象monitor,即當(dāng)前實(shí)例對象就是鎖對象,每次當(dāng)線程進(jìn)入synchronized包裹的代碼塊時就會要求當(dāng)前線程持有monitor實(shí)例對象鎖,如果當(dāng)前有其他線程正持有該對象鎖,那么新到的線程就必須等待,這樣也就保證了每次只有一個線程執(zhí)行synchronized內(nèi)包裹的代碼塊

從上面的分析中可以看出,悲觀鎖是獨(dú)占和排他的,只要操作資源都會對資源進(jìn)行加鎖。假設(shè)讀多寫少的情況下,使用悲觀鎖的效果就不是很好。這時就引出了接下來要講的樂觀鎖。

 

樂觀鎖

樂觀鎖,顧名思義它總是假設(shè)最好的情況,線程每次去拿數(shù)據(jù)時都認(rèn)為別人不會修改,所以不會上鎖,但是在更新的時候會判斷一下在此期間別人有沒有去更新這個數(shù)據(jù),如果這個數(shù)據(jù)沒有被更新,當(dāng)前線程將自己修改的數(shù)據(jù)成功寫入。如果數(shù)據(jù)已經(jīng)被其他線程更新,則根據(jù)不同的實(shí)現(xiàn)方式執(zhí)行不同的操作(例如報錯或者自動重試)。如圖所示:

java并發(fā)編程中悲觀鎖和樂觀鎖是什么意思  

一般樂觀鎖在java中是通過無鎖編程實(shí)現(xiàn)的,最常見的就是CAS算法,比如Java并發(fā)包中的原子類的遞增操作就是通過CAS算法實(shí)現(xiàn)的。

CAS算法,其實(shí)就是Compare And Swap(比較與交換)的意思。目的就是將內(nèi)存的值更新為需要的值,但是有個條件,內(nèi)存值必須與期待的原內(nèi)存值相同。展開來說,我們有三個變量,內(nèi)存值M,期望的內(nèi)存值E,更新值U,只有當(dāng)M==E時,才會將M更新為U

CAS算法實(shí)現(xiàn)的樂觀鎖在很多地方有應(yīng)用,比如并發(fā)包的原子類AtomicInteger類。在自增的時候就使用到CAS算法。

public final int getAndIncrement() {
    return unsafe.getAndAddInt(this, valueOffset, 1);
}

//var1 是this指針
//var2 是偏移量
//var4 是自增量
public final int getAndAddInt(Object var1, long var2, int var4) {
    int var5;
    do {
        //獲取內(nèi)存,稱之為期待的內(nèi)存值E
        var5 = this.getIntVolatile(var1, var2);
        //var5 + var4的結(jié)果是更新值U
        //這里使用JNI方法,每個線程將自己內(nèi)存中的內(nèi)存值M與var5期望值比較,
        //如果相同則更新為var5 + var4,返回true跳出循環(huán)。
        //如果不相同,則把內(nèi)存值M更新為最新的內(nèi)存值,然后自旋,直到更新成功為止
    } while(!this.compareAndSwapInt(var1, var2, var5, var5 + var4));
 //返回更新后的值
    return var5;
}

public final native boolean compareAndSwapInt(Object var1, long var2, int var4, int var5);
 

所以可以看出CAS算法其實(shí)是無鎖的。好處是在讀多寫少的情況下,性能是比較好的。那么CAS算法的缺點(diǎn)其實(shí)也是很明顯的。

  • ABA問題。線程C將內(nèi)存值A(chǔ)改成了B后,又改成了A,而線程D會認(rèn)為內(nèi)存值A(chǔ)沒有改變過,這個問題就稱為ABA問題。解決辦法很簡單,在變量前面加上版本號,每次變量更新的時候變量的     版本號都+1,即     A->B->A就變成了     1A->2B->3A。
  • 在寫多讀少的情況下,也就是頻繁更新數(shù)據(jù),那么會導(dǎo)致其他線程經(jīng)常更新失敗,那么就會進(jìn)入自旋,自旋時會     占用CPU資源。如果資源競爭激烈,多線程自旋的時間長,導(dǎo)致     消耗資源。
 

使用場景

讀多寫少的場景下,更新時很少發(fā)生沖突,使用樂觀鎖,減少了上鎖和釋放鎖的開銷,可以有效地提升系統(tǒng)的性能。

相反,在寫多讀少的場景下,如果使用樂觀鎖會導(dǎo)致更新時經(jīng)常產(chǎn)生沖突,然后線程會循環(huán)重試,這樣會增大CPU的消耗。在這種情況下,建議可以使用悲觀鎖

以上是“java并發(fā)編程中悲觀鎖和樂觀鎖是什么意思”這篇文章的所有內(nèi)容,感謝各位的閱讀!希望分享的內(nèi)容對大家有幫助,更多相關(guān)知識,歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道!

本文標(biāo)題:java并發(fā)編程中悲觀鎖和樂觀鎖是什么意思
本文來源:http://chinadenli.net/article28/gjcjjp.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供面包屑導(dǎo)航、網(wǎng)站設(shè)計(jì)公司自適應(yīng)網(wǎng)站、軟件開發(fā)網(wǎng)站建設(shè)、企業(yè)建站

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)

網(wǎng)站托管運(yùn)營