电脑知识|欧美黑人一区二区三区|软件|欧美黑人一级爽快片淫片高清|系统|欧美黑人狂野猛交老妇|数据库|服务器|编程开发|网络运营|知识问答|技术教程文章 - 好吧啦网

您的位置:首頁技術文章
文章詳情頁

詳解java 中的CAS與ABA

瀏覽:6日期:2022-08-13 09:13:37
1. 獨占鎖:

屬于悲觀鎖,有共享資源,需要加鎖時,會以獨占鎖的方式導致其它需要獲取鎖才能執行的線程掛起,等待持有鎖的錢程釋放鎖。傳統的關系型數據庫里邊就用到了很多這種鎖機制,比如行鎖,表鎖等,讀鎖,寫鎖等,都是在做操作之前先上鎖。Java中synchronized和ReentrantLock等獨占鎖就是悲觀鎖的思想。

1.1 樂觀鎖的操作

多線程并發修改一個值時的實現:

public class SimulatedCAS {//加volatile的目的是利用其happens-before原則,保證線程可見性 private volatile int value; public synchronized int getValue() { return value; } public synchronized int compareAndSwap(int expectedValue, int newValue) { int oldValue = value; if (value == expectedValue) value = newValue; return oldValue; }}2. 樂觀鎖:

總是假設最好的情況,每次去拿數據的時候都認為別人不會修改,所以不會上鎖,但是在更新的時候會判斷一下在此期間別人有沒有去更新這個數據,可以使用版本號機制和CAS算法實現。樂觀鎖適用于多讀的應用類型,這樣可以提高吞吐量,像數據庫提供的類似于write_condition機制,其實都是提供的樂觀鎖。 在Java中java.util.concurrent.atomic包下面的原子變量類就是使用了樂觀鎖的一種實現方式CAS實現的。樂觀鎖一般會使用版本號機制或CAS算法實現。

2.1 CAS操作 CAS 操作包含三個操作數 —— 內存位置(V)、預期原值(A)和新值(B)。如果內存位置的值與預期原值相匹配,那么處理器會自動將該位置值更新為新值。否則,處理器不做任何操作。無論哪種情況,它都會在 CAS 指令之前返回該位置的值。(在 CAS 的一些特殊情況下將僅返回 CAS 是否成功,而不提取當前值。)CAS 有效地說明了“我認為位置 V 應該包含值 A;如果包含該值,則將 B 放到這個位置;否則,不要更改該位置,只告訴我這個位置現在的值即可。” 通常將 CAS 用于同步的方式是從地址 V 讀取值 A,執行多步計算來獲得新值 B,然后使用 CAS 將 V 的值從 A 改為 B。如果 V 處的值尚未同時更改,則 CAS 操作成功。 類似于 CAS 的指令允許算法執行讀-修改-寫操作,而無需害怕其他線程同時修改變量,因為如果其他線程修改變量,那么 CAS 會檢測它(并失敗),算法可以對該操作重新計算。 CAS實現計數器的操作:

public class CasCounter { private SimulatedCAS value; public int getValue() {return value.getValue(); } public int increment() {int oldValue = value.getValue();while (value.compareAndSwap(oldValue, oldValue + 1) != oldValue) oldValue = value.getValue();return oldValue + 1; }}3. 原子變量類

JDK5.0之后加入了java.util.concurrent.atomic 包,其中的AtomicInteger; AtomicLong; AtomicReference; AtomicBoolean 等都是在CAS基礎上實現的。

4. CAS的缺陷 循環時間太長,如果自旋長時間不成功,會給cpu帶來極大的開銷,有興趣的可以使用JMH測試下AtomicLong 和 LongAdder的性能。 ABA問題: CAS需要檢查待操作值有沒有發生改變,如果沒有發生改變則更新。 但是存在這樣一種情況:如果一個值原來是A,變成了B,然后又變成了A,那么在CAS檢查的時候會發現沒有改變,但是實質上它已經發生了改變,這就是所謂的ABA問題。 在運用CAS做Lock-Free操作中有一個經典的ABA問題:比如線程1從內存位置V中取出A,這時另一個線程2也從內存中取出A,并且線程2進行了操作之后變成了B,然線程2又將V位置數據變成了A,這時候線程1進行CAS操作發現內存中仍然是A,然后線程1 操作成功。看上去是成功了,實際上有隱藏的問題: 現有一個用單向鏈表實現的FIFO堆棧,棧頂為A,這時線程1已經知道A.next為B,然后希望用CAS將棧頂替換為B,在線程1執行上面這條指令之前,線程2 介入,將A、B出棧,再push D、C、A,此時A位于棧頂,B已經不在棧中;此時線程1執行CAS,發現棧頂仍為A,所以CAS成功,即將棧頂變成B,但實際上此時B與 當前棧中元素D、C沒有關系,B.next為null,這樣一來就直接把C、D丟掉了。 對于ABA問題其解決方案是加上版本號,即在每個變量都加上一個版本號,每次改變時加1,即A —> B —> A,變成A(1) —> B(2) —> A(3)。 java中AtomicStampedReference也實現了這個作用,它通過包裝[E,Integer]的元組來對對象標記版本戳stamp,從而避免ABA問題。

public class AtomicTest {private static AtomicInteger atomicInteger = new AtomicInteger(100);private static AtomicStampedReference<Integer> atomicStampedReference =new AtomicStampedReference<Integer>(99, 0);public static void main(String[] args) throws InterruptedException {Thread thread1 = new Thread(() -> {atomicInteger.compareAndSet(99, 100);atomicInteger.compareAndSet(100, 99);});Thread thread2 = new Thread(() -> {try {TimeUnit.SECONDS.sleep(1);}catch (InterruptedException e){e.printStackTrace();}boolean b = atomicInteger.compareAndSet(99, 100);System.out.println(b);});thread1.start();thread2.start();thread1.join();thread2.join();Thread refT1 = new Thread(() -> {try {TimeUnit.SECONDS.sleep(1);} catch (InterruptedException e) {e.printStackTrace();}atomicStampedReference.compareAndSet(99, 100,atomicStampedReference.getStamp(), atomicStampedReference.getStamp() + 1);atomicStampedReference.compareAndSet(100, 99,atomicStampedReference.getStamp(), atomicStampedReference.getStamp() + 1);});Thread refT2 = new Thread(() -> {int stamp = atomicStampedReference.getStamp();System.out.println('before sleep : stamp = ' + stamp); // stamp = 0try {TimeUnit.SECONDS.sleep(2);} catch (InterruptedException e) {e.printStackTrace();}System.out.println('after sleep : stamp = ' + atomicStampedReference.getStamp());//stamp = 1boolean c3 = atomicStampedReference.compareAndSet(99, 100, stamp, stamp+1);System.out.println(c3);//false});refT1.start();refT2.start();}}

結果如下:

truebefore sleep : stamp = 0after sleep : stamp = 2false

也就是說AtomicInteger更新成功,而AtomicStampedReference更新失敗。

以上就是詳解java 中的CAS與ABA的詳細內容,更多關于java 中的CAS與ABA的資料請關注好吧啦網其它相關文章!

標簽: Java
相關文章:
主站蜘蛛池模板: 艺术生文化课培训|艺术生文化课辅导冲刺-济南启迪学校 | 气密性检测仪_气密性检测设备_防水测试仪_密封测试仪-岳信仪器 | 浇注料-高铝砖耐火砖-郑州凯瑞得窑炉耐火材料有限公司 | 短信营销平台_短信群发平台_106短信发送平台-河南路尚 | 生鲜配送系统-蔬菜食材配送管理系统-连锁餐饮订货配送软件-挪挪生鲜供应链管理软件 | 南京租车,南京汽车租赁,南京包车,南京会议租车-南京七熹租车 | 深圳工程师职称评定条件及流程_深圳职称评审_职称评审-职称网 | 重庆监控_电子围栏设备安装公司_门禁停车场管理系统-劲浪科技公司 | H型钢切割机,相贯线切割机,数控钻床,数控平面钻,钢结构设备,槽钢切割机,角钢切割机,翻转机,拼焊矫一体机 | 灌木树苗-绿化苗木-常绿乔木-价格/批发/基地 - 四川成都途美园林 | 氧化锆纤维_1800度高温退火炉_1800度高温烧结炉-南京理工宇龙新材料股份有限公司 | 砂石生产线_石料生产线设备_制砂生产线设备价格_生产厂家-河南中誉鼎力智能装备有限公司 | 睿婕轻钢别墅_钢结构别墅_厂家设计施工报价 | 耐高温硅酸铝板-硅酸铝棉保温施工|亿欧建设工程 | 应急灯_消防应急灯_应急照明灯_应急灯厂家-大成智慧官网 | 大型冰雕-景区冰雕展制作公司,3D创意设计源头厂家-[赛北冰雕] | 工控机,嵌入式主板,工业主板,arm主板,图像采集卡,poe网卡,朗锐智科 | 河南生物显微镜,全自动冰冻切片机-河南荣程联合科技有限公司 | 广州小程序开发_APP开发公司_分销商城系统定制_小跑科技 | 东莞喷砂机-喷砂机-喷砂机配件-喷砂器材-喷砂加工-东莞市协帆喷砂机械设备有限公司 | 安徽免检低氮锅炉_合肥燃油锅炉_安徽蒸汽发生器_合肥燃气锅炉-合肥扬诺锅炉有限公司 | 商标转让-商标注册-商标查询-软著专利服务平台 - 赣江万网 | 法兰螺母 - 不锈钢螺母制造厂家 - 万千紧固件--螺母街 | 定制液氮罐_小型气相液氮罐_自增压液氮罐_班德液氮罐厂家 | 佛山市钱丰金属不锈钢蜂窝板定制厂家|不锈钢装饰线条|不锈钢屏风| 电梯装饰板|不锈钢蜂窝板不锈钢工艺板材厂家佛山市钱丰金属制品有限公司 | 阴离子聚丙烯酰胺价格_PAM_高分子聚丙烯酰胺厂家-河南泰航净水材料有限公司 | 电脑知识|软件|系统|数据库|服务器|编程开发|网络运营|知识问答|技术教程文章 - 好吧啦网 | 中图网(原中国图书网):网上书店,尾货特色书店,30万种特价书低至2折! | 干洗加盟网-洗衣店品牌排行-干洗设备价格-干洗连锁加盟指南 | 粘度计维修,在线粘度计,二手博勒飞粘度计维修|收购-天津市祥睿科技有限公司 | SF6环境监测系统-接地环流在线监测装置-瑟恩实业 | 宁夏档案密集柜,智能密集柜,电动手摇密集柜-盛隆柜业宁夏档案密集柜厂家 | 超声波焊接机,振动摩擦焊接机,激光塑料焊接机,超声波焊接模具工装-德召尼克(常州)焊接科技有限公司 | 华东师范大学在职研究生招生网_在职研究生招生联展网 | 广州印刷厂_广州彩印厂-广州艺彩印务有限公司 | 胶水,胶粘剂,AB胶,环氧胶,UV胶水,高温胶,快干胶,密封胶,结构胶,电子胶,厌氧胶,高温胶水,电子胶水-东莞聚力-聚厉胶粘 | 施工电梯_齿条货梯_烟囱电梯_物料提升机-河南大诚机械制造有限公司 | 东莞市超赞电子科技有限公司 全系列直插/贴片铝电解电容,电解电容,电容器 | 车件|铜件|车削件|车床加工|五金冲压件-PIN针,精密车件定制专业厂商【东莞品晔】 | 安平县鑫川金属丝网制品有限公司,声屏障,高速声屏障,百叶孔声屏障,大弧形声屏障,凹凸穿孔声屏障,铁路声屏障,顶部弧形声屏障,玻璃钢吸音板 | 蒸汽热收缩机_蒸汽发生器_塑封机_包膜机_封切收缩机_热收缩包装机_真空机_全自动打包机_捆扎机_封箱机-东莞市中堡智能科技有限公司 |