摘要:前言為了研究對原子類的實現(xiàn),從類開始,分析如果對原子操作的實現(xiàn)。保存著基礎(chǔ)數(shù)據(jù),使用修飾,可以保證該值對內(nèi)存可見,也是原子類實現(xiàn)的理論保障。使用自旋鎖來處理并發(fā)問題。
前言
為了研究Java對原子類的實現(xiàn),從AtomicInteger類開始,分析Java如果對原子操作的實現(xiàn)。
原子操作是指不會被線程調(diào)度機(jī)制打斷的操作;這種操作一旦開始,就一直運行到結(jié)束,中間不會有任何上下文的切換。
注:原子操作可以是一個步驟,也可以是多個操作步驟,但是其順序不可以被打亂,也不可以被切割只執(zhí)行其中的一部分。
首先從AtomicInteger類的屬性聊起:
// setup to use Unsafe.compareAndSwapInt for updates private static final Unsafe unsafe = Unsafe.getUnsafe(); private static final long valueOffset; private volatile int value;
該類共有三個成員屬性。
unsafe:該類是JDK提供的可以對內(nèi)存直接操作的工具類。
valueOffset:該值保存著AtomicInteger基礎(chǔ)數(shù)據(jù)的內(nèi)存地址,方便unsafe直接對內(nèi)存的操作。
value:保存著AtomicInteger基礎(chǔ)數(shù)據(jù),使用volatile修飾,可以保證該值對內(nèi)存可見,也是原子類實現(xiàn)的理論保障。
再談靜態(tài)代碼塊(初始化)
try { valueOffset = unsafe.objectFieldOffset (AtomicInteger.class.getDeclaredField("value")); } catch (Exception ex) { throw new Error(ex); } }
該過程實際上就是計算成員變量value的內(nèi)存偏移地址,計算后,可以更直接的對內(nèi)存進(jìn)行操作。
了解核心方法compareAndSet(int expect,int update):
public final boolean compareAndSet(int expect, int update) { return unsafe.compareAndSwapInt(this, valueOffset, expect, update); }
在該方法中調(diào)用了unsafe提供的服務(wù):
public final native boolean compareAndSwapInt(Object var1, long var2, int var4, int var5);
下面看看這個類在JDK中是如何實現(xiàn)的:
jboolean sun::misc::Unsafe::compareAndSwapInt (jobject obj, jlong offset,jint expect, jint update) { jint *addr = (jint *)((char *)obj + offset); //1 return compareAndSwap (addr, expect, update); } static inline bool compareAndSwap (volatile jlong *addr, jlong old, jlong new_val) { jboolean result = false; spinlock lock; //2 if ((result = (*addr == old))) //3 *addr = new_val; //4 return result; //5 }
通過對象地址和value的偏移量地址,來計算value的內(nèi)存地址。
使用自旋鎖來處理并發(fā)問題。
比較內(nèi)存中的值與調(diào)用方法時調(diào)用方所期待的值。
如果3中的比較符合預(yù)期,則重置內(nèi)存中的值。
如果成功置換則返回true,否則返回false;
綜上所述:compareAndSet的實現(xiàn)依賴于兩個條件:
volatile原語:保證在操作內(nèi)存的值時,該值的狀態(tài)為最新的。(被volatile所修飾的變量在讀取值時都會從變量的地址中讀取,而不是從寄存器中讀取,保證數(shù)據(jù)對所有線程都是可見的)
Unsafe類:通過該類提供的功能,可以直接對內(nèi)存進(jìn)行操作。
了解常見操作getAndIncrement():
return unsafe.getAndAddInt(this, valueOffset, 1); }
同樣使用unsafe提供的方法:
public final int getAndAddInt(Object var1, long var2, int var4) { int var5; do { var5 = this.getIntVolatile(var1, var2);//1 } while(!this.compareAndSwapInt(var1, var2, var5, var5 + var4));//2 return var5; } //getIntVolatile方法native實現(xiàn) jint sun::misc::Unsafe::getIntVolatile (jobject obj, jlong offset) { volatile jint *addr = (jint *) ((char *) obj + offset); //3 jint result = *addr; //4 read_barrier (); //5 return result; //6 } inline static void read_barrier(){ __asm__ __volatile__("" : : : "memory"); }
通過volatile方法獲取當(dāng)前內(nèi)存中該對象的value值。
計算value的內(nèi)存地址。
將值賦值給中間變量result。
插入讀屏障,保證該屏障之前的讀操作后后續(xù)的操作可見。
返回當(dāng)前內(nèi)存值
通過compareAndSwapInt操作對value進(jìn)行+1操作,如果再執(zhí)行該操作過程中,內(nèi)存數(shù)據(jù)發(fā)生變更,則執(zhí)行失敗,但循環(huán)操作直至成功。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/70830.html
摘要:前言今天的筆記來了解一下原子操作以及中如何實現(xiàn)原子操作。概念原子本意是不能被進(jìn)一步分割的最小粒子,而原子操作意為不可被中斷的一個或一系列操作。處理器實現(xiàn)原子操作處理器會保證基本內(nèi)存操作的原子性。 showImg(https://segmentfault.com/img/bVVIRA?w=1242&h=536); 前言 今天的筆記來了解一下原子操作以及Java中如何實現(xiàn)原子操作。 概念 ...
摘要:并發(fā)教程原子變量和原文譯者飛龍協(xié)議歡迎閱讀我的多線程編程系列教程的第三部分。如果你能夠在多線程中同時且安全地執(zhí)行某個操作,而不需要關(guān)鍵字或上一章中的鎖,那么這個操作就是原子的。當(dāng)多線程的更新比讀取更頻繁時,這個類通常比原子數(shù)值類性能更好。 Java 8 并發(fā)教程:原子變量和 ConcurrentMap 原文:Java 8 Concurrency Tutorial: Synchroni...
摘要:本文探討并發(fā)中的其它問題線程安全可見性活躍性等等。當(dāng)閉鎖到達(dá)結(jié)束狀態(tài)時,門打開并允許所有線程通過。在從返回時被叫醒時,線程被放入鎖池,與其他線程競爭重新獲得鎖。 本文探討Java并發(fā)中的其它問題:線程安全、可見性、活躍性等等。 在行文之前,我想先推薦以下兩份資料,質(zhì)量很高:極客學(xué)院-Java并發(fā)編程讀書筆記-《Java并發(fā)編程實戰(zhàn)》 線程安全 《Java并發(fā)編程實戰(zhàn)》中提到了太多的術(shù)語...
摘要:今天給大家總結(jié)一下,面試中出鏡率很高的幾個多線程面試題,希望對大家學(xué)習(xí)和面試都能有所幫助。指令重排在單線程環(huán)境下不會出先問題,但是在多線程環(huán)境下會導(dǎo)致一個線程獲得還沒有初始化的實例。使用可以禁止的指令重排,保證在多線程環(huán)境下也能正常運行。 下面最近發(fā)的一些并發(fā)編程的文章匯總,通過閱讀這些文章大家再看大廠面試中的并發(fā)編程問題就沒有那么頭疼了。今天給大家總結(jié)一下,面試中出鏡率很高的幾個多線...
閱讀 3946·2023-04-25 16:32
閱讀 2255·2021-09-28 09:36
閱讀 2076·2021-09-06 15:02
閱讀 715·2021-09-02 15:21
閱讀 951·2019-08-30 15:56
閱讀 3554·2019-08-30 15:45
閱讀 1750·2019-08-30 13:09
閱讀 410·2019-08-29 16:05