java併發編程JUC第十二篇:AtomicInteger原子整型

AtomicInteger 類底層存儲一個int值,並提供方法對該int值進行原子操做。AtomicInteger 做爲java.util.concurrent.atomic包的一部分,從Java 1.5開始引入。vue

1. AtomicInteger基礎用法

經過下文的AtomicInteger構造方法,能夠建立一個AtomicInteger對象,該對象的初始值默認爲0。AtomicInteger提供get和set方法,獲取底層int整數值,與設置int整數值java

//初始值爲0的atomicInteger對象
AtomicInteger atomicInteger = new AtomicInteger();  
 
//初始值爲200的atomicInteger對象
AtomicInteger atomicInteger = new AtomicInteger(200);
 
int currentValue = atomicInteger.get();         //100
atomicInteger.set(2453);                        //如今的值是 2453

可是上面的方法,對於AtomicInteger而言並非它的核心內容,AtomicInteger核心內容體如今它的原子性,咱們下文介紹。算法

2. 何時須要使用AtomicInteger

咱們一般在如下的兩種場景下使用AtomicIntegerspring

  1. 多線程併發場景下操做一個計數器,須要保證計數器操做的原子性。
  2. 進行數值比較,若是給定值與當前值相等,進行數值的更新操做,並實現操做的非阻塞算法。

2.1. 原子計數器場景

AtomicInteger做爲一個計數器使用,AtomicInteger提供了若干方法進行加法、減法的原子操做。後端

好比從一個map裏面獲取值,用get()方法,這是第一個操做;獲取到值以後給這個值加上n,這是第二個操做;將進行過加法運算的值,再次放入map裏面是第三個操做。所謂操做的原子性是指:在多線程併發的場景下,上面的三個操做是原子性的,也就是不可分割的。不會出現A線程get了數值,B線程同時也get到了該數值,兩個線程同時爲該值作運算並前後再次放入的狀況,這種狀況對於 AtomicInteger而言是不會出現的, AtomicInteger操做是線程安全的、不可分割的。
  • addAndGet()- 將給定的值加到當前值上,並在加法後返回新值,並保證操做的原子性。
  • getAndAdd()- 將給定的值加到當前值上,並返回舊值,並保證操做的原子性。
  • incrementAndGet()- 將當前值增長1,並在增長後返回新值。它至關於++i操做,並保證操做的原子性。
  • getAndIncrement()- 將當前值增長1並返回舊值。至關於++i操做,並保證操做的原子性。
  • decrementAndGet()- 將當前值減去1,並在減去後返回新值,至關於i--操做,並保證操做的原子性。
  • getAndDecrement()- 將當前值減去1,並返回舊值。它至關於 --i操做,並保證操做的原子性。

下面是AtomicInteger原子性操做方法的例子數組

public class Main {
    public static void main(String[] args) {
        //初始值爲100的atomic Integer
        AtomicInteger atomicInteger = new AtomicInteger(100);
         
        System.out.println(atomicInteger.addAndGet(2));         //加2並返回102
        System.out.println(atomicInteger);                      //102
         
        System.out.println(atomicInteger.getAndAdd(2));         //先獲取102,再加2
        System.out.println(atomicInteger);                      //104
         
        System.out.println(atomicInteger.incrementAndGet());    //加1再獲取105   
        System.out.println(atomicInteger);                      //105   
                 
        System.out.println(atomicInteger.getAndIncrement());    //先獲取105再加1
        System.out.println(atomicInteger);                      //106
         
        System.out.println(atomicInteger.decrementAndGet());    //減1再獲取105
        System.out.println(atomicInteger);                      //105
         
        System.out.println(atomicInteger.getAndDecrement());    //先獲取105,再減1
        System.out.println(atomicInteger);                      //104
    }
}

2.2. 數值比對及交換操做

compareAndSet操做將一個內存位置的內容與一個給定的值進行比較,只有當它們相同時,纔會將該內存位置的內容修改成一個給定的新值。這個過程是以單個原子操做的方式完成的。安全

compareAndSet方法:若是當前值==預期值,則將值設置爲給定的更新值。springboot

boolean compareAndSet(int expect, int update)
  • expect是預期值
  • update是更新值

AtomicInteger compareAndSet() 方法的例子多線程

import java.util.concurrent.atomic.AtomicInteger;
 
public class Main {
    public static void main(String[] args) {
        //初始值爲100的atomic Integer
        AtomicInteger atomicInteger = new AtomicInteger(100);


        //當前值100 = 預期值100,因此設置atomicInteger=110
        boolean isSuccess = atomicInteger.compareAndSet(100,110);  
        System.out.println(isSuccess);      //輸出結果爲true表示操做成功


        //當前值110 = 預期值100?不相等,因此atomicInteger仍然等於110
        isSuccess = atomicInteger.compareAndSet(100,120);  
        System.out.println(isSuccess);      //輸出結果爲false表示操做失敗
    }
}

3. 總結

AtomicInteger能夠幫助咱們在不使用synchronized同步鎖的狀況下,實如今多線程場景下int數值操做的線程安全,操做的原子性。而且使用AtomicInteger來實現int數值的原子操做,遠比使用synchronized同步鎖效率更高。
java.util.concurrent.atomic包不只爲咱們提供了AtomicInteger,還提供了AtomicBoolean布爾原子操做類、AtomicLong長整型布爾原子操做類、AtomicReference對象原子操做類、AtomicIntegerArray整型數組原子操做類、AtomicLongArray長整型數組原子操做類、AtomicReferenceArray對象數組原子操做類。併發

歡迎關注個人博客,裏面有不少精品合集

本文轉載註明出處(必須帶鏈接,不能只轉文字):字母哥博客 - zimug.com

以爲對您有幫助的話,幫我點贊、分享!您的支持是我不竭的創做動力! 。另外,筆者最近一段時間輸出了以下的精品內容,期待您的關注。

相關文章
相關標籤/搜索