xylz,imxylz

          關(guān)注后端架構(gòu)、中間件、分布式和并發(fā)編程

             :: 首頁(yè) :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理 ::
            111 隨筆 :: 10 文章 :: 2680 評(píng)論 :: 0 Trackbacks

          在這一部分開(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ì)于AtomicIntegerFieldUpdaterAtomicLongFieldUpdater只能修改int/long類(lèi)型的字段,不能修改其包裝類(lèi)型(Integer/Long)。如果要修改包裝類(lèi)型就需要使用AtomicReferenceFieldUpdater

           

          在下面的例子中描述了操作的方法。

           

          package xylz.study.concurrency.atomic;

          import java.util.concurrent.atomic.AtomicIntegerFieldUpdater;

          public class AtomicIntegerFieldUpdaterDemo {

            
          class DemoData{
                
          public volatile int value1 = 1;
                
          volatile int value2 = 2;
                
          protected volatile int value3 = 3;
                
          private volatile int value4 = 4;
             }

              AtomicIntegerFieldUpdater
          <DemoData> getUpdater(String fieldName) {
                 
          return AtomicIntegerFieldUpdater.newUpdater(DemoData.class, fieldName);
              }

             
          void doit() {
                  DemoData data
          = new DemoData();
                  System.out.println(
          "1 ==> "+getUpdater("value1").getAndSet(data, 10));
                  System.out.println(
          "3 ==> "+getUpdater("value2").incrementAndGet(data));
                  System.out.println(
          "2 ==> "+getUpdater("value3").decrementAndGet(data));
                  System.out.println(
          "true ==> "+getUpdater("value4").compareAndSet(data, 4, 5));
              }

             
          public static void main(String[] args) {
                  AtomicIntegerFieldUpdaterDemo demo
          = new AtomicIntegerFieldUpdaterDemo();
                  demo.doit();
              }

          }
           


          在上面的例子中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ì)思想。



          ©2009-2014 IMXYLZ |求賢若渴
          posted on 2010-07-02 14:19 imxylz 閱讀(48176) 評(píng)論(6)  編輯  收藏 所屬分類(lèi): J2EE

          評(píng)論

          # re: 深入淺出 Java Concurrency (3): 原子操作 part 2 2010-07-02 21:33 18傲骨中文
          又是高深學(xué)堂~~~  回復(fù)  更多評(píng)論
            

          # re: 深入淺出 Java Concurrency (3): 原子操作 part 2 2010-07-03 10:22 FineReport——報(bào)表技術(shù)領(lǐng)跑者
          很好很強(qiáng)大,哈哈!頂了~  回復(fù)  更多評(píng)論
            

          # re: 深入淺出 Java Concurrency (3): 原子操作 part 2[未登錄](méi) 2010-11-23 17:48 Nicholas
          在上面的例子中DemoData的字段value3/value4對(duì)于AtomicIntegerFieldUpdaterDemo類(lèi)是不可見(jiàn)的,因此通過(guò)反射是不能直接修改其值的。

          老實(shí)說(shuō),這句我實(shí)在沒(méi)有看懂,根據(jù)debug的結(jié)果來(lái)看,data中的value3值確實(shí)最終變?yōu)榱?.  回復(fù)  更多評(píng)論
            

          # re: 深入淺出 Java Concurrency (3): 原子操作 part 2 2010-11-23 20:22 xylz
          @Nicholas
          看上面約束2。
          換句話說(shuō)DemoData的value3/value4字段的修飾符protected/private導(dǎo)致這兩個(gè)字段對(duì)于類(lèi)AtomicIntegerFieldUpdaterDemo 來(lái)說(shuō)是不可見(jiàn)的,因此不能夠通過(guò)AtomicIntegerFieldUpdater來(lái)修改此值。因此運(yùn)行時(shí)下面兩句會(huì)得到一個(gè)非法訪問(wèn)的異常。
          System.out.println("2 ==> "+getUpdater("value3").decrementAndGet(data));
          System.out.println("true ==> "+getUpdater("value4").compareAndSet(data, 4, 5));  回復(fù)  更多評(píng)論
            

          # re: 深入淺出 Java Concurrency (3): 原子操作 part 2 2013-06-13 11:38 海藍(lán)
          應(yīng)該是可見(jiàn)的吧@xylz
            回復(fù)  更多評(píng)論
            

          # re: 深入淺出 Java Concurrency (3): 原子操作 part 2 2016-03-10 16:30 問(wèn)問(wèn)問(wèn)問(wèn)
          @Nicholas
          @海藍(lán)
          對(duì)啊,默認(rèn)的可以訪問(wèn)到,protected怎么可能訪問(wèn)不到  回復(fù)  更多評(píng)論
            


          ©2009-2014 IMXYLZ
          主站蜘蛛池模板: 博野县| 治多县| 翼城县| 阿克| 苍梧县| 莱芜市| 茶陵县| 黑水县| 江口县| 普定县| 三门峡市| 五莲县| 德惠市| 城固县| 萍乡市| 武安市| 安岳县| 平阴县| 且末县| 夏津县| 朝阳县| 梁平县| 清徐县| 金平| 射阳县| 陵水| 同江市| 独山县| 新营市| 德州市| 昭平县| 千阳县| 阿勒泰市| 汪清县| 金湖县| 清丰县| 建阳市| 诸暨市| 扎赉特旗| 宁国市| 青龙|