<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                # Java線程(十):CAS ## 前言 在Java并發包中有這樣一個包,java.util.concurrent.atomic,該包是對Java部分數據類型的原子封裝,在原有數據類型的基礎上,提供了原子性的操作方法,保證了線程安全。下面以AtomicInteger為例,來看一下是如何實現的。 ~~~ public?final?int?incrementAndGet()?{?? ????for?(;;)?{?? ????????int?current?=?get();?? ????????int?next?=?current?+?1;?? ????????if?(compareAndSet(current,?next))?? ????????????return?next;?? ????}?? }?? ~~~ ~~~ public?final?int?decrementAndGet()?{?? ????for?(;;)?{?? ????????int?current?=?get();?? ????????int?next?=?current?-?1;?? ????????if?(compareAndSet(current,?next))?? ????????????return?next;?? ????}?? }?? ~~~ 以這兩個方法為例,incrementAndGet方法相當于原子性的++i,decrementAndGet方法相當于原子性的--i(根據[第一章](http://blog.csdn.net/ghsau/article/details/7421217)和[第二章](http://blog.csdn.net/ghsau/article/details/7424694)我們知道++i或--i不是一個原子性的操作),這兩個方法中都沒有使用阻塞式的方式來保證原子性(如Synchronized),那它們是如何保證原子性的呢,下面引出CAS。 ## Compare And Swap CAS 指的是現代 CPU 廣泛支持的一種對內存中的共享數據進行操作的一種特殊指令。這個指令會對內存中的共享數據做原子的讀寫操作。簡單介紹一下這個指令的操作過程:首先,CPU 會將內存中將要被更改的數據與期望的值做比較。然后,當這兩個值相等時,CPU 才會將內存中的數值替換為新的值。否則便不做操作。最后,CPU 會將舊的數值返回。這一系列的操作是原子的。它們雖然看似復雜,但卻是 Java 5 并發機制優于原有鎖機制的根本。簡單來說,CAS 的含義是“我認為原有的值應該是什么,如果是,則將原有的值更新為新值,否則不做修改,并告訴我原來的值是多少”。(這段描述引自《Java并發編程實踐》) 簡單的來說,CAS有3個操作數,內存值V,舊的預期值A,要修改的新值B。**當且僅當預期值A和內存值V相同時,將內存值V修改為B,否則返回V**。這是一種樂觀鎖的思路,它相信在它修改之前,沒有其它線程去修改它;而Synchronized是一種悲觀鎖,它認為在它修改之前,一定會有其它線程去修改它,悲觀鎖效率很低。下面來看一下AtomicInteger是如何利用CAS實現原子性操作的。 ## volatile變量 ` private?volatile?int?value;??` 首先聲明了一個volatile變量value,在[第二章](http://blog.csdn.net/ghsau/article/details/7424694)我們知道volatile保證了變量的內存可見性,也就是所有工作線程中同一時刻都可以得到一致的值。 ~~~ public?final?int?get()?{?? ????return?value;?? }?? ~~~ ## Compare And Set ~~~ //?setup?to?use?Unsafe.compareAndSwapInt?for?updates?? private?static?final?Unsafe?unsafe?=?Unsafe.getUnsafe();?? private?static?final?long?valueOffset;//?注意是靜態的?? ?? static?{?? ??try?{?? ????valueOffset?=?unsafe.objectFieldOffset?? ????????(AtomicInteger.class.getDeclaredField("value"));//?反射出value屬性,獲取其在內存中的位置?? ??}?catch?(Exception?ex)?{?throw?new?Error(ex);?}?? }?? ?? public?final?boolean?compareAndSet(int?expect,?int?update)?{?? ??return?unsafe.compareAndSwapInt(this,?valueOffset,?expect,?update);?? }?? ~~~ 比較并設置,這里利用Unsafe類的JNI方法實現,使用CAS指令,可以保證讀-改-寫是一個原子操作。compareAndSwapInt有4個參數,this - 當前AtomicInteger對象,Offset - value屬性在內存中的位置(需要強調的是不是value值在內存中的位置),expect - 預期值,update - 新值,根據上面的CAS操作過程,當內存中的value值等于expect值時,則將內存中的value值更新為update值,并返回true,否則返回false。在這里我們有必要對Unsafe有一個簡單點的認識,從名字上來看,不安全,確實,這個類是用于執行低級別的、不安全操作的方法集合,這個類中的方法大部分是對內存的直接操作,所以不安全,但當我們使用反射、并發包時,都間接的用到了Unsafe。 ## 循環設置 現在在來看開篇提到的兩個方法,我們拿incrementAndGet來分析一下其實現過程。 ~~~ public?final?int?incrementAndGet()?{?? ????for?(;;)?{//?這樣優于while(true)?? ????????int?current?=?get();//?獲取當前值?? ????????int?next?=?current?+?1;//?設置更新值?? ????????if?(compareAndSet(current,?next))?? ????????????return?next;?? ????}?? }?? ~~~ 循環內,獲取當前值并設置更新值,調用compareAndSet進行CAS操作,如果成功就返回更新至,否則重試到成功為止。這里可能存在一個隱患,那就是循環時間過長,總是在當前線程compareAndSet時,有另一個線程設置了value(點子太背了),這個當然是屬于小概率時間,目前Java貌似還不能處理這種情況。 ## 缺點 雖然使用CAS可以實現非阻塞式的原子性操作,但是會產生ABA問題,關于ABA問題,計劃單拿出一章來整理。 (完)
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看