原标題:Java并發程式設計之原子操作類
原子操作類簡介
當更新一個變量的時候,多出現資料争用的時候可能出現所意想不到的情況。這時的一般政策是使用synchronized解決,因為synchronized能夠保證多個線程不會同時更新該變量。然而,從jdk 5之後,提供了粒度更細、量級更輕,并且在多核處理器具有高性能的原子操作類。因為原子操作類把競争的範圍縮小到單個變量上,這可以算是粒度最細的情況了。
原子操作類相當于泛化的volatile變量,能夠支援原子讀取-修改-寫操作。比如AtomicInteger表示一個int類型的數值,提供了get和set方法,這些volatile類型的變量在讀取與寫入上有着相同的記憶體語義。原子操作類共有13個類,在java.util.concurrent.atomic包下,可以分為四種類型的原子更新類:原子更新基本類型、原子更新數組類型、原子更新引用和原子更新屬性。
下面将分别介紹這四種原子操作類。
原子更新基本類型
使用原子方式更新基本類型,共包括3個類:
AtomicBoolean:原子更新布爾變量
AtomicInteger:原子更新整型變量
AtomicLong:原子更新長整型變量
具體到每個類的源代碼中,提供的方法基本相同,這裡以AtomicInteger為例進行說明。AtomicInteger提供的部分方法如下:

為了說明AtomicInteger的原子性,這裡代碼示範多線程對一個int值進行自增操作,最後輸出結果,代碼如下:
輸出結果如下:
可以看到在多線程的情況下,得到的結果是正确的,但是如果僅僅使用int類型的成員變量則可能得到不同的結果。這裡的關鍵在于getAndIncrement是原子操作,那麼是如何保證的呢?
getAndIncrement方法的源碼如下:
到這裡可以發現最終調用了native方法來保證更新的原子性。
原子更新數組
通過原子更新數組裡的某個元素,共有3個類:
AtomicIntegerArray:原子更新整型數組的某個元素
AtomicLongArray:原子更新長整型數組的某個元素
AtomicReferenceArray:原子更新引用類型數組的某個元素
AtomicIntegerArray常用的方法有:
int addAndSet(int i, int delta):以原子方式将輸入值與數組中索引為i的元素相加
boolean compareAndSet(int i, int expect, int update):如果目前值等于預期值,則以原子方式更新數組中索引為i的值為update值
示例代碼如下:
運作結果是:
數組value通過構造的方式傳入AtomicIntegerArray中,實際上AtomicIntegerArray會将目前數組拷貝一份,是以在數組拷貝的操作不影響原數組的值。
原子更新引用類型
需要更新引用類型往往涉及多個變量,早atomic包有三個類:
AtomicReference:原子更新引用類型
AtomicReferenceFieldUpdater:原子更新引用類型裡的字段
AtomicMarkableReference:原子更新帶有标記位的引用類型。
下面以AtomicReference為例進行說明:
可以看到user被成功更新。
原子更新字段類
如果需要原子更新某個類的某個字段,就需要用到原子更新字段類,可以使用以下幾個類:
AtomicIntegerFieldUpdater:原子更新整型字段
AtomicLongFieldUpdater:原子更新長整型字段
AtomicStampedReference:原子更新帶有版本号的引用類型。
要想原子更新字段,需要兩個步驟:
每次必須使用newUpdater建立一個更新器,并且需要設定想要更新的類的字段
更新類的字段(屬性)必須為public volatile
下面的代碼示範如何使用原子更新字段類更新字段:
輸出的結果如下:
至此,我們知道了如何使用原子操作類在不同場景下的基本用法。傳回搜狐,檢視更多
責任編輯: