中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Java中CAS的底層實現原理是什么

發布時間:2021-08-09 17:05:44 來源:億速云 閱讀:251 作者:Leah 欄目:編程語言

Java中CAS的底層實現原理是什么,很多新手對此不是很清楚,為了幫助大家解決這個難題,下面小編將為大家詳細講解,有這方面需求的人可以來學習下,希望你能有所收獲。

一、CAS(compareAndSwap)的概念

CAS,全稱Compare And Swap(比較與交換),解決多線程并行情況下使用鎖造成性能損耗的一種機制。

CAS(V, A, B),V為內存地址、A為預期原值,B為新值。如果內存地址的值與預期原值相匹配,那么將該位置值更新為新值。否則,說明已經被其他線程更新,處理器不做任何操作;無論哪種情況,它都會在 CAS 指令之前返回該位置的值。而我們可以使用自旋鎖,循環CAS,重新讀取該變量再嘗試再次修改該變量,也可以放棄操作。

二、CAS(compareAndSwap)的產生

為什么需要CAS機制呢?我們先從一個錯誤現象談起。我們經常使用volatile關鍵字修飾某一個變量,表明這個變量是全局共享的一個變量,同時具有了可見性和有序性。但是卻沒有原子性。比如說一個常見的操作a++。這個操作其實可以細分成三個步驟:

(1)從內存中讀取a

(2)對a進行加1操作

(3)將a的值重新寫入內存中

在單線程狀態下這個操作沒有一點問題,但是在多線程中就會出現各種各樣的問題了。因為可能一個線程對a進行了加1操作,還沒來得及寫入內存,其他的線程就讀取了舊值。造成了線程的不安全現象。

Volatile關鍵字可以保證線程間對于共享變量的可見性可有序性,可以防止CPU的指令重排序(DCL單例),但是無法保證操作的原子性,所以jdk1.5之后引入CAS利用CPU原語保證線程操作的院子性。

CAS操作由處理器提供支持,是一種原語。原語是操作系統或計算機網絡用語范疇。是由若干條指令組成的,用于完成一定功能的一個過程,具有不可分割性,即原語的執行必須是連續的,在執行過程中不允許被中斷。如 Intel 處理器,比較并交換通過指令的 cmpxchg 系列實現。

三、CAS(compareAndSwap)的原理探究

CAS的實現主要在JUC中的atomic包,我們以AtomicInteger類為例:

通過代碼追溯,可以看出JAVA中的CAS操作都是通過sun包下Unsafe類實現,而Unsafe類中的方法都是native方法,由JVM本地實現,所以最終的實現是基于C、C++在操作系統之上操作

Unsafe類,在sun.misc包下,不屬于Java標準。Unsafe類提供一系列增加Java語言能力的操作,如內存管理、操作類/對象/變量、多線程同步等

//var1為CAS操作的對象,offset為var1某個屬性的地址偏移值,expected為期望值,var2為要設置的值,利用JNI來完成CPU指令的操作public final native boolean compareAndSwapObject(Object var1, long var2, Object var4, Object var5);public final native boolean compareAndSwapInt(Object var1, long var2, int var4, int var5);public final native boolean compareAndSwapLong(Object var1, long var2, long var4, long var6);public native Object getObjectVolatile(Object var1, long var2);public native void putObjectVolatile(Object var1, long var2, Object var4);

Hotspot源碼中關于unsafe的實現hotspot\src\share\vm\prims\unsafe.cppUNSAFE_ENTRY(jboolean, Unsafe_CompareAndSwapInt(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jint e, jint x)) UnsafeWrapper("Unsafe_CompareAndSwapInt"); oop p = JNIHandles::resolve(obj);根據偏移量,計算value的地址。這里的offset就是 AtomaicInteger中的valueOffset jint* addr = (jint *) index_oop_from_field_offset_long(p, offset); return (jint)(Atomic::cmpxchg(x, addr, e)) == e;UNSAFE_END\hotspot\src\share\vm\runtime\atomic.cppunsigned Atomic::cmpxchg(unsigned int exchange_value,             volatile unsigned int* dest, unsigned int compare_value) { assert(sizeof(unsigned int) == sizeof(jint), "more work to do"); return (unsigned int)Atomic::cmpxchg((jint)exchange_value, (volatile jint*)dest,                    (jint)compare_value);}根據操作系統類型調用不同平臺下的重載函數,這個在預編譯期間編譯器會決定調用哪個平臺下的重載

可以看到調用了“Atomic::cmpxchg”方法,“Atomic::cmpxchg”方法在linux_x86和windows_x86的實現如下

linux_x86底層實現\hotspot\src\os_cpu\linux_x86\vm\atomic_linux_x86.inline.hppinline jint   Atomic::cmpxchg  (jint   exchange_value, volatile jint*   dest, jint   compare_value) { int mp = os::is_MP(); __asm__ volatile (LOCK_IF_MP(%4) "cmpxchgl %1,(%3)"          : "=a" (exchange_value)          : "r" (exchange_value), "a" (compare_value), "r" (dest), "r" (mp)          : "cc", "memory"); return exchange_value;}

windows_x86底層實現hotspot\src\os_cpu\windows_x86\vmatomic_linux_x86.inline.hppinline jint   Atomic::cmpxchg  (jint   exchange_value, volatile jint*   dest, jint   compare_value) { // alternative for InterlockedCompareExchange int mp = os::is_MP(); __asm {  mov edx, dest  mov ecx, exchange_value  mov eax, compare_value  LOCK_IF_MP(mp)  cmpxchg dword ptr [edx], ecx }}

總結:根據資料查詢,其實CAS底層實現根據不同的操作系統會有不同重載,CAS的實現離不開處理器的支持。

核心代碼就是一條帶lock 前綴的 cmpxchg 指令,即lock cmpxchg dword ptr [edx], ecx

Atomic::cmpxchg方法解析:

mp是“os::is_MP()”的返回結果,“os::is_MP()”是一個內聯函數,用來判斷當前系統是否為多處理器。

如果當前系統是多處理器,該函數返回1。

否則,返回0。

LOCK_IF_MP(mp)會根據mp的值來決定是否為cmpxchg指令添加lock前綴。

如果通過mp判斷當前系統是多處理器(即mp值為1),則為cmpxchg指令添加lock前綴。

否則,不加lock前綴。

這是一種優化手段,認為單處理器的環境沒有必要添加lock前綴,只有在多核情況下才會添加lock前綴,因為lock會導致性能下降。cmpxchg是匯編指令,作用是比較并交換操作數。

四、CAS機制的優缺點

4.1 優點

cas是一種樂觀鎖,而且是一種非阻塞的輕量級的樂觀鎖,什么是非阻塞式的呢?其實就是一個線程想要獲得鎖,對方會給一個回應表示這個鎖能不能獲得。在資源競爭不激烈的情況下性能高,相比synchronized重量鎖,synchronized會進行比較復雜的加鎖,解鎖和喚醒操作。

4.2 缺點

1)循環時間長開銷大,占用CPU資源

2)只能保證一個共享變量的原子操作

3)ABA問題

4.3 解決ABA問題

1)添加版本號

2)AtomicStampedReference

java并發包為了解決這個問題,提供了一個帶有標記的原子引用類“AtomicStampedReference”,它可以通過控制變量值的版本來保證CAS的正確性。因此,在使用CAS前要考慮清楚“ABA”問題是否會影響程序并發的正確性,如果需要解決ABA問題,改用傳統的互斥同步可能會比原子類更高效。

看完上述內容是否對您有幫助呢?如果還想對相關知識有進一步的了解或閱讀更多相關文章,請關注億速云行業資訊頻道,感謝您對億速云的支持。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

云阳县| 建瓯市| 沛县| 黄冈市| 利津县| 武清区| 日喀则市| 江孜县| 绥阳县| 呼玛县| 贵德县| 壤塘县| 伊春市| 伊金霍洛旗| 松桃| 维西| 岑溪市| 区。| 广宁县| 深泽县| 阳城县| 呈贡县| 乐亭县| 辛集市| 阿尔山市| 永顺县| 荆州市| 萨迦县| 芜湖县| 山丹县| 江永县| 剑川县| 全椒县| 定边县| 荥阳市| 吕梁市| 达孜县| 乌兰浩特市| 桓仁| 常州市| 湘潭市|