在這一部分開(kāi)始討論數(shù)組原子操作和一些其他的原子操作。
AtomicIntegerArray/AtomicLongArray/AtomicReferenceArray的API類(lèi)似,選擇有代表性的AtomicIntegerArray來(lái)描述這些問(wèn)題。
int get(int i)
獲取位置 i
的當(dāng)前值。很顯然,由于這個(gè)是數(shù)組操作,就有索引越界的問(wèn)題(IndexOutOfBoundsException異常)。
對(duì)于下面的API起始和AtomicInteger是類(lèi)似的,這種通過(guò)方法、參數(shù)的名稱(chēng)就能夠得到函數(shù)意義的寫(xiě)法是非常值得稱(chēng)贊的。在《重構(gòu):改善既有代碼的設(shè)計(jì)》和《代碼整潔之道》中都非常推崇這種做法。
void set(int i, int newValue)
void lazySet(int i, int newValue)
int getAndSet(int i, int newValue)
boolean compareAndSet(int i, int expect, int update)
boolean weakCompareAndSet(int i, int expect, int update)
int getAndIncrement(int i)
int getAndDecrement(int i)
int getAndAdd(int i, int delta)
int incrementAndGet(int i)
int decrementAndGet(int i)
int addAndGet(int i, int delta)
整體來(lái)說(shuō),數(shù)組的原子操作在理解上還是相對(duì)比較容易的,這些API就是有多使用才能體會(huì)到它們的好處,而不僅僅是停留在理論階段。
現(xiàn)在關(guān)注字段的原子更新。
AtomicIntegerFieldUpdater<T>/AtomicLongFieldUpdater<T>/AtomicReferenceFieldUpdater<T,V>是基于反射的原子更新字段的值。
相應(yīng)的API也是非常簡(jiǎn)單的,但是也是有一些約束的。
(1)字段必須是volatile類(lèi)型的!在后面的章節(jié)中會(huì)詳細(xì)說(shuō)明為什么必須是volatile,volatile到底是個(gè)什么東西。
(2)字段的描述類(lèi)型(修飾符public/protected/default/private)是與調(diào)用者與操作對(duì)象字段的關(guān)系一致。也就是說(shuō)調(diào)用者能夠直接操作對(duì)象字段,那么就可以反射進(jìn)行原子操作。但是對(duì)于父類(lèi)的字段,子類(lèi)是不能直接操作的,盡管子類(lèi)可以訪問(wèn)父類(lèi)的字段。
(3)只能是實(shí)例變量,不能是類(lèi)變量,也就是說(shuō)不能加static關(guān)鍵字。
(4)只能是可修改變量,不能使final變量,因?yàn)閒inal的語(yǔ)義就是不可修改。實(shí)際上final的語(yǔ)義和volatile是有沖突的,這兩個(gè)關(guān)鍵字不能同時(shí)存在。
(5)對(duì)于AtomicIntegerFieldUpdater和AtomicLongFieldUpdater只能修改int/long類(lèi)型的字段,不能修改其包裝類(lèi)型(Integer/Long)。如果要修改包裝類(lèi)型就需要使用AtomicReferenceFieldUpdater。
在下面的例子中描述了操作的方法。





























在上面的例子中DemoData的字段value3/value4對(duì)于AtomicIntegerFieldUpdaterDemo類(lèi)是不可見(jiàn)的,因此通過(guò)反射是不能直接修改其值的。
AtomicMarkableReference類(lèi)描述的一個(gè)<Object,Boolean>的對(duì),可以原子的修改Object或者Boolean的值,這種數(shù)據(jù)結(jié)構(gòu)在一些緩存或者狀態(tài)描述中比較有用。這種結(jié)構(gòu)在單個(gè)或者同時(shí)修改Object/Boolean的時(shí)候能夠有效的提高吞吐量。
AtomicStampedReference類(lèi)維護(hù)帶有整數(shù)“標(biāo)志”的對(duì)象引用,可以用原子方式對(duì)其進(jìn)行更新。對(duì)比AtomicMarkableReference類(lèi)的<Object,Boolean>,AtomicStampedReference維護(hù)的是一種類(lèi)似<Object,int>的數(shù)據(jù)結(jié)構(gòu),其實(shí)就是對(duì)對(duì)象(引用)的一個(gè)并發(fā)計(jì)數(shù)。但是與AtomicInteger不同的是,此數(shù)據(jù)結(jié)構(gòu)可以攜帶一個(gè)對(duì)象引用(Object),并且能夠?qū)Υ藢?duì)象和計(jì)數(shù)同時(shí)進(jìn)行原子操作。
在后面的章節(jié)中會(huì)提到“ABA問(wèn)題”,而AtomicMarkableReference/AtomicStampedReference在解決“ABA問(wèn)題”上很有用。
原子操作的使用大概就是這么多,大體來(lái)說(shuō)還算是比較清晰的,在下一個(gè)章節(jié)中,將對(duì)象原子操作進(jìn)行總結(jié),重點(diǎn)介紹下原子操作的原理和設(shè)計(jì)思想。