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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

Java中CAS操作本身怎么保证原子性及其原理分析

發布時間:2024/3/24 java 47 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Java中CAS操作本身怎么保证原子性及其原理分析 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

Java中CAS操作是怎么保證原子性的?

在學習Java多線程時我們會接觸到CAS這樣一個概念,CAS其實就是Compare And Swap的一個縮寫。Compare And Swap,顧名思義就是比較并交換,其實就是把當前值與你預期的值進行一個比較,如果一樣再進行修改,否則不修改并返回失敗。這里我解釋一下,當前值與預期值的一個概念:多線程環境下很可能發生當我拿到一個值還沒修改的時候,別的線程已經把這個值修改掉了,這樣就會引發線程安全問題,所以CAS操作就是在修改前用一個當前值和期望值來進行比較,只有相等,即沒有其他線程修改過這個值的時候(也可能發生一個線程改了,又有一個線程又改回來的情況,CAS無法感知到這種操作,它還是會認為數據沒有發生變化而進行修改。這種情況可以利用AtomicStampedReference和AtomicMarkableReference解決,兩者根據應用場景不同一定區別,這里不做闡述),才進行修改,從而保證操作的原子性。

可以看到compareAndSet方法中的expect(期望值),update(修改的值)。

CAS本身操作的原子性

那么CAS這個操作本身又是怎么保證原子性的呢?可以想象:比較——修改這是兩個動作,可能我比較的時候它是一樣的,當我修改的時候它卻被別的線程修改了。這就涉及到CAS本身這個操作是原子的,也就是不被其他線程所干擾的。這是利用CPU的原語來實現的。我們知道Java方法無法直接訪問底層系統,需要通過本地(Native)方法來訪問,Unsafe相當于一個橋梁,基于該類可以連接底層的操作系統直接操作特定的內存數據,Unsafe類存在sun.misc包中,其內部方法操作可以像C指針一樣直接操作內存,因此Java中的CAS操作的執行依賴于Unsafe類的方法。(Unsafe類很重要!不知道的同學可以多去了解,建議自己利用反射獲取unsafe對象自己寫一些東西,比如自己寫一個原子類)

進入compareAndSet方法我們發現他返回的是unsafe的compareAndSwapInt方法:

進入Unsafe類的native方法compareAndSwapInt,既然是native方法,那就不涉及到Java的代碼了,調用UnSafe類中的CAS方法,也就是這個本地native方法,JVM會幫我們實現出CAS匯編指令,這是一種完全依賴于硬件的功能,通過它實現了原子操作,由于CAS是一種系統原語,原語屬于操作系統用于范疇,是由若干條指令組成,用于完成某個功能的一個過程,并且原語的執行必須是連續的,在執行過程中不允許被中斷,也就是說CAS是一條CPU的原子指令,不會造成所謂的數據不一致的問題,也就是說CAS是線程安全的。

注意Unsafe類的所有方法都是native修飾的,也就是說unsafe類中的方法都直接調用操作系統底層資源執行相應的任務。

變量valueOffset

表示該變量值在內存中的偏移地址,因為Unsafe就是根據內存偏移地址獲取數據的,這個變量我們在自己利用unsafe對象寫一些操作的時候會用到,其實Compare操作也是一個內存比較的過程。

附上一個自己寫的原子類:

import sun.misc.Unsafe;import java.lang.reflect.Field;class MyAtomicInteger {private volatile int value;private static final long valueOffset;static final Unsafe UNSAFE;static {try {Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe");theUnsafe.setAccessible(true);Unsafe unsafe = (Unsafe) theUnsafe.get(null); //這個成員變量就是Unsafe類型UNSAFE = unsafe;} catch (NoSuchFieldException | IllegalAccessException e) {throw new Error(e);}}static {try {//獲取value的偏移量,用于Unsafe直接訪問該屬性valueOffset = UNSAFE.objectFieldOffset(MyAtomicInteger.class.getDeclaredField("value"));} catch (NoSuchFieldException e) {e.printStackTrace();;throw new RuntimeException(e);}}public int getValue() {return value;}public void increment(int amount){while (true){int prev = this.value;int next = prev - amount;//CASif (UNSAFE.compareAndSwapInt(this,valueOffset,prev,next)){break;}}} }

?

?

以上只是個人學習中一些感悟與分享,如有錯誤歡迎指正與交流。

總結

以上是生活随笔為你收集整理的Java中CAS操作本身怎么保证原子性及其原理分析的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。