java cas原理_Java并发之原子变量及CAS算法-上篇
Java并發(fā)之原子變量及CAS算法-上篇
編輯
?
概述
本文主要講在Java并發(fā)編程的時(shí)候,如果保證變量的原子性,在JDK提供的類中是怎么保證變量原子性的呢?。對(duì)應(yīng)Java中的包是:java.util.concurrent.atomic包下。因?yàn)樯婕暗搅薈AS算法,需要對(duì)CAS算法講解及CAS算法三個(gè)問題怎么解決以及和Synchroized比較。文章比較長,所以就分為上下兩個(gè)篇幅講解。本文是上篇《Java并發(fā)之原子變量及CAS算法-上篇》
本文是《凱哥分享Java并發(fā)編程之J.U.C包講解》系列教程中的一篇。如果想系統(tǒng)學(xué)習(xí),建議從第一篇開始看。
原子變量案例
在Java中有一種寫法:int i = 10; i++ 這種寫法。
我們先來看看:
編輯
?
輸入的是0還是1呢 ?
I++輸出0的原因分析
答案是:0。為什么呢?凱哥把編譯后的class文件反編譯,咱們看:
編輯
?
說明:i的操作是i++;y的操作是++y.
從反編譯后的代碼,我們可以看到i++在JVM中的操作,總共分三步:
第一步:聲明變量var10000 ,然后將i賦值給var10000,此時(shí)var10000的值是0;
第二步:聲明變量var3 然后把i+1 賦值給var3,此時(shí),var3的值等于1了;
第三步:將變量var10000的值又賦值給了i,此時(shí)因?yàn)関ar10000的值是0,所以i的值也是0
所以在sysout(i)的時(shí)候,就輸出了0.
我們分析上面1,2,3步驟,可以發(fā)現(xiàn)。其實(shí)i++執(zhí)行的是:讀取-修改-重寫 三個(gè)操作。
既然讀寫操作,就會(huì)涉及到變量原子性。測試在多線程下變量原子性
測試多線程下的變量原子性
那么,如果我們把對(duì)i的操作放到多個(gè)線程中操作結(jié)果會(huì)是什么樣的呢?
線程操作I的代碼:
編輯
?
開啟十個(gè)線程同時(shí)操作i的代碼:
編輯
?
我們來看看運(yùn)行結(jié)果:
編輯
?
從運(yùn)行結(jié)果中,我們可以看到,線程Thread-5和線程Thread-8的值是一樣的。
根據(jù)上面運(yùn)行的場景,我們發(fā)現(xiàn),變量i其實(shí)是十個(gè)線程中的共享變量。從運(yùn)行的結(jié)果來看,多個(gè)線程操作后,結(jié)果出問題了。
不同線程在內(nèi)存中運(yùn)行模擬圖:
編輯
?
線程1;線程2;以及主線程之間運(yùn)行關(guān)系,可以詳見凱哥上一篇文章:《Java并發(fā)之內(nèi)存可見性問題怎么解決》。這篇文章詳細(xì)講解了怎么關(guān)系。
已經(jīng)看過凱哥上一篇文章或者是知道volatile關(guān)鍵字的朋友可能要說,這不就是線程之間變量可見性問題嘛。使用volatile關(guān)鍵字修飾i就可以了。真的可以了嗎?
我們修改程序,用volatile來修飾,看看運(yùn)行結(jié)果:
使用volatile關(guān)鍵字是否能解決多線程情況下變量原子性呢?
用volatile來修飾變量:
private volatile int shardData = 0;
運(yùn)行結(jié)果:
編輯
?
我們發(fā)現(xiàn),就算使用volatile關(guān)鍵字修飾了,依然存在多線程下變量原子性的問題。
怎么解決這種并發(fā)下變量原子性問題呢?
Java的atomic包
在jdk1.5以后,Java為我們提供了一個(gè)常用的原子變量。都在:java.util.concureent.atomic包下。我們來看看,都有哪些:
編輯
?
編輯
?
編輯
?
從JDK的API文檔中(凱哥使用的是JDK1.8的API)我們可以看到常用的原子性變量。
怎么保證原子性呢?
那么,在atomic包下的這些類怎么保證原子性呢?
1:該包下的變量都是使用volatile關(guān)鍵字來修飾。
解決了多線程之間變量可見性。
Int類型的原子性對(duì)象AtomicInteger對(duì)象中:
編輯
?
用于對(duì)象的AtomicReference對(duì)象中:
編輯
?
都是使用volat關(guān)鍵字修飾的。
2:使用CAS算法
保持了變量的原子性
總結(jié):
在Java的JDK中提供了concurrent.atomic包,使用這個(gè)包下的對(duì)象創(chuàng)建的變量就能保證原子性。
保證原子性的策略:
1:變量都是用Volatile關(guān)鍵字修飾。來保證內(nèi)存可見性
2:使用CAS算法,來保證原子性。
編輯
?
下篇預(yù)告:
在下一篇文章中,我們主要講解CAS算法原理及CAS算法會(huì)參數(shù)哪些問題(三個(gè)問題)?JDK是怎么解決的?修改i++使其成為具有原子性變量怎么實(shí)現(xiàn)。
總結(jié)
以上是生活随笔為你收集整理的java cas原理_Java并发之原子变量及CAS算法-上篇的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 怎么把u盘的注册表修改 修改U盘的注册表
- 下一篇: java sound 多线程同一音频文件