日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

一篇文章带你解析,乐观锁与悲观锁的优缺点

發(fā)布時(shí)間:2025/3/20 编程问答 25 豆豆
生活随笔 收集整理的這篇文章主要介紹了 一篇文章带你解析,乐观锁与悲观锁的优缺点 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

樂(lè)觀鎖與悲觀鎖

概述

樂(lè)觀鎖

總是假設(shè)最好的情況,每次去讀數(shù)據(jù)的時(shí)候都認(rèn)為別人不會(huì)修改,所以不會(huì)上鎖, 但是在更新的時(shí)候會(huì)判斷一下在此期間有沒(méi)有其他線程更新該數(shù)據(jù), 可以使用版本號(hào)機(jī)制和CAS算法實(shí)現(xiàn)。 樂(lè)觀鎖適用于多讀的應(yīng)用類型,這樣可以提高吞吐量,像數(shù)據(jù)庫(kù)提供的類似于write_condition機(jī)制,其實(shí)都是提供的樂(lè)觀鎖。 在Java中java.util.concurrent.atomic包下面的原子變量類就是基于CAS實(shí)現(xiàn)的樂(lè)觀鎖。

悲觀鎖

總是假設(shè)最壞的情況,每次去讀數(shù)據(jù)的時(shí)候都認(rèn)為別人會(huì)修改,所以每次在讀數(shù)據(jù)的時(shí)候都會(huì)上鎖, 這樣別人想讀取數(shù)據(jù)就會(huì)阻塞直到它獲取鎖 (共享資源每次只給一個(gè)線程使用,其它線程阻塞,用完后再把資源轉(zhuǎn)讓給其它線程)。 傳統(tǒng)的關(guān)系型數(shù)據(jù)庫(kù)里邊就用到了很多悲觀鎖機(jī)制,比如行鎖,表鎖等,讀鎖,寫(xiě)鎖等,都是在做操作之前先上鎖。 Java中synchronized和ReentrantLock等獨(dú)占鎖就是悲觀鎖思想的實(shí)現(xiàn)。

使用場(chǎng)景

  • 樂(lè)觀鎖適用于寫(xiě)比較少的情況下(多讀場(chǎng)景),即沖突真的很少發(fā)生的時(shí)候,這樣可以省去了鎖的開(kāi)銷,加大了系統(tǒng)的整個(gè)吞吐量。

  • 悲觀鎖適用于讀比較少的情況下(多寫(xiě)場(chǎng)景),如果是多寫(xiě)的情況,一般會(huì)經(jīng)常產(chǎn)生沖突,這就會(huì)導(dǎo)致上層應(yīng)用會(huì)不斷的進(jìn)行retry,這樣反倒是降低了性能,所以一般多寫(xiě)的場(chǎng)景下用悲觀鎖就比較合適。

樂(lè)觀鎖好比生活中樂(lè)觀的人總是想著事情往好的方向發(fā)展,悲觀鎖好比生活中悲觀的人總是想著事情往壞的方向發(fā)展。 這兩種人各有優(yōu)缺點(diǎn),不能不以場(chǎng)景而定說(shuō)一種人好于另外一種人。

樂(lè)觀鎖常見(jiàn)的兩種實(shí)現(xiàn)方式

版本控制

一般是在數(shù)據(jù)表中加上一個(gè)數(shù)據(jù)版本號(hào)version字段,表示數(shù)據(jù)被修改的次數(shù),當(dāng)數(shù)據(jù)被修改時(shí),version++即可。 當(dāng)線程A要更新數(shù)據(jù)值時(shí),在讀取數(shù)據(jù)的同時(shí)也會(huì)讀取version值, 在提交更新時(shí),若剛才讀取到的version值為當(dāng)前數(shù)據(jù)庫(kù)中的version值相等時(shí)才更新, 否則重試更新操作,直到更新成功。

舉個(gè)例子:

假設(shè)數(shù)據(jù)庫(kù)中帳戶信息表中有一個(gè) version 字段,并且 version=1;而當(dāng)前帳戶余額字段(balance)為 $100 。操作員 A 此時(shí)將其讀出 (version=1),并從其帳戶余額中扣除 $50($100-$50)。操作員 A 操作的同事,操作員B 也讀入此用戶信息(version=1),并從其帳戶余額中扣除 $20($100-$20)。操作員 A 完成了修改工作,version++(version=2),連同帳戶扣除后余額(balance=$50),提交至數(shù)據(jù)庫(kù)更新, 此時(shí)由于提交數(shù)據(jù)版本大于數(shù)據(jù)庫(kù)記錄當(dāng)前版本,數(shù)據(jù)被更新,數(shù)據(jù)庫(kù)記錄 version 更新為 2 。操作員 B 完成了操作,也將版本號(hào)version++(version=2)試圖向數(shù)據(jù)庫(kù)提交數(shù)據(jù)(balance=$80), 但此時(shí)比對(duì)數(shù)據(jù)庫(kù)記錄版本時(shí)發(fā)現(xiàn),操作員 B 提交的數(shù)據(jù)版本號(hào)為 2 ,數(shù)據(jù)庫(kù)記錄當(dāng)前版本也為 2 , 不滿足**提交版本必須大于記錄當(dāng)前版本才能執(zhí)行更新**的樂(lè)觀鎖策略,因此,操作員 B 的提交被駁回。復(fù)制代碼

避免了操作員 B 用基于 version=1 的舊數(shù)據(jù)修改的結(jié)果覆蓋操作員A 的操作結(jié)果的可能。

CAS算法

硬件支持的原子性操作最典型的是:比較并交換(Compare-and-Swap,CAS)。 CAS 指令需要有 3 個(gè)操作數(shù),分別是內(nèi)存地址 V、舊的預(yù)期值 A 和新值 B。 當(dāng)執(zhí)行操作時(shí),只有當(dāng) V 的值等于 A,才將 V 的值更新為 B。

//著名的CAS //var1是比較值所屬的對(duì)象,var2需要比較的值(但實(shí)際是使用地址偏移量來(lái)實(shí)現(xiàn)的), //如果var1對(duì)象中偏移量為var2處的值等于var4,那么將該處的值設(shè)置為var5并返回true,如果不等于var4則返回false。 public final native boolean compareAndSwapInt(Object var1, long var2, int var4, int var5);復(fù)制代碼

樂(lè)觀鎖的缺點(diǎn)

1.ABA問(wèn)題

如果一個(gè)變量初次讀取的時(shí)候是 A 值,它的值被改成了 B,后來(lái)又被改回為 A,那 CAS 操作就會(huì)誤認(rèn)為它從來(lái)沒(méi)有被改變過(guò)。

J.U.C 包提供了一個(gè)帶有標(biāo)記的原子引用類 AtomicStampedReference 來(lái)解決這個(gè)問(wèn)題, 它可以通過(guò)控制變量值的版本來(lái)保證 CAS 的正確性。 大部分情況下 ABA 問(wèn)題不會(huì)影響程序并發(fā)的正確性, 如果需要解決 ABA 問(wèn)題,改用傳統(tǒng)的互斥同步可能會(huì)比原子類更高效。

2.自旋時(shí)間長(zhǎng)開(kāi)銷大

自旋CAS(也就是不成功就一直循環(huán)執(zhí)行直到成功)如果長(zhǎng)時(shí)間不成功,會(huì)給CPU帶來(lái)非常大的執(zhí)行開(kāi)銷。 如果JVM能支持處理器提供的pause指令那么效率會(huì)有一定的提升,pause指令有兩個(gè)作用, 第一它可以延遲流水線執(zhí)行指令(de-pipeline),使CPU不會(huì)消耗過(guò)多的執(zhí)行資源, 延遲的時(shí)間取決于具體實(shí)現(xiàn)的版本,在一些處理器上延遲時(shí)間是零。 第二它可以避免在退出循環(huán)的時(shí)候因內(nèi)存順序沖突(memory order violation) 而引起CPU流水線被清空(CPU pipeline flush),從而提高CPU的執(zhí)行效率。

3.只能保證一個(gè)共享變量的原子操作 CAS只對(duì)單個(gè)共享變量有效,當(dāng)操作涉及跨多個(gè)共享變量時(shí)CAS無(wú)效。 但是從 JDK 1.5開(kāi)始,提供了AtomicReference類來(lái)保證引用對(duì)象之間的原子性, 可以把多個(gè)變量封裝成對(duì)象里來(lái)進(jìn)行 CAS 操作. 所以我們可以使用鎖或者利用AtomicReference類把多個(gè)共享變量封裝成一個(gè)共享變量來(lái)操作。

CAS與synchronized的使用情景

  • 對(duì)于資源競(jìng)爭(zhēng)較少(線程沖突較輕)的情況, 使用synchronized同步鎖進(jìn)行線程阻塞和喚醒切換以及用戶態(tài)內(nèi)核態(tài)間的切換操作額外浪費(fèi)消耗cpu資源; 而CAS基于硬件實(shí)現(xiàn),不需要進(jìn)入內(nèi)核,不需要切換線程,操作自旋幾率較少,因此可以獲得更高的性能。

  • 對(duì)于資源競(jìng)爭(zhēng)嚴(yán)重(線程沖突嚴(yán)重)的情況,CAS自旋的概率會(huì)比較大, 從而浪費(fèi)更多的CPU資源,效率低于synchronized。



轉(zhuǎn)載于:https://juejin.im/post/5cdfa98c51882525f52cf6f9

總結(jié)

以上是生活随笔為你收集整理的一篇文章带你解析,乐观锁与悲观锁的优缺点的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。