JAVA併發編程之-原子變量

做者:畢來生
微信:878799579

一、什麼是原子變量?

​ 原子變量保證了該變量的全部操做都是原子的,不會由於多線程的同時訪問而致使髒數據的讀取問題。java

二、經過synchronized保證原子操做
  1. 獲取鎖對象
  2. 獲取失敗/獲取不到 ->阻塞隊列等待
  3. 釋放鎖對象
三、Atomic之AtomicInteger源碼分析

java.util.concurrent.atomic包下幫助咱們提供了不少原子性的支持,請參考下圖微信

在這裏插入圖片描述

  • AtomicInteger和AtomicIntegerArray:基於Integer類型
  • AtomicBoolean:基於Boolean類型
  • AtomicLong和AtomicLongArray:基於Long類型
  • AtomicReference和AtomicReferenceArray:基於引用類型多線程


    構造方法以下併發

private volatile int value;

  /**
   * Creates a new AtomicInteger with the given initial value.
   *
   * @param initialValue the initial value
   */
  public AtomicInteger(int initialValue) {
      value = initialValue;
  }

  /**
   * Creates a new AtomicInteger with initial value {@code 0}.
   */
  public AtomicInteger() {
  }

若是經過構造方法設置原子變量。如不設置初始值則會默認初始化爲0。ide

如下爲方法爲AtomicInteger基於原子操做經常使用方法源碼分析

//獲取當前原子變量中的值併爲其設置新值
public final int getAndSet(int newValue)

//比較當前的value是否等於expect,若是是設置爲update並返回true,不然返回false
public final boolean compareAndSet(int expect, int update)

//獲取當前的value值並自增一
public final int getAndIncrement()

//獲取當前的value值並自減一
public final int getAndDecrement()

//獲取當前的value值併爲value加上delta
public final int getAndAdd(int delta)
四、實戰演練

在多線程下。我但願對num = 0;進行自增,10個線程,每一個線程對變量自增10000次。結果應該是100000纔對。atom

首先咱們先來一個錯誤示範:spa

package org.bilaisheng.juc;

/**
 * @Author: bilaisheng
 * @Wechat: 878799579
 * @Date: 2019/1/1 21:58
 * @Todo: AtomicInteger 原子性錯誤示範。僅演示使用
 * @Version : JDK11 , IDEA2018
 */
public class AtomicIntegerErrorTest {

    // 舉例10條線程併發,實際條數請參考本身場景
    private static final int THREAD_COUNT = 10;

    private static int num = 0;

    public static void main(String[] args) {

        Thread[] threads = new Thread[THREAD_COUNT];

        for (int i = 0; i < THREAD_COUNT; i++) {
            threads[i] = new Thread(new Runnable() {
                @Override
                public void run() {
                    // 此處設置10000.過小看不到效果。請酌情設置
                    for (int j = 1; j <=10000 ; j++) {
                        // 如想要看到結果請放開下行註釋
                        //System.out.println(Thread.currentThread().getName() +" num = "+num);
                        num++ ;
                    }
                }
            });
            threads[i].start();
        }

        System.out.println(Thread.currentThread().getName());
        System.out.println(Thread.activeCount());

        while (Thread.activeCount()>2){
            Thread.yield();
        }

        System.out.println(num);
    }

}

運行結果舉例兩張以下圖所示。每次運行結果都不相同線程

在這裏插入圖片描述

在這裏插入圖片描述

接下來咱們的AtomicInteger就該登場了3d

package org.bilaisheng.juc;

import java.util.concurrent.atomic.AtomicInteger;

/**
 * @Author: bilaisheng
 * @Wechat: 878799579
 * @Date: 2019/1/1 23:02
 * @Todo:
 * @Version : JDK11 , IDEA2018
 */
public class AtomicIntegerTest {


    private static final int THREADS_CONUT = 10;
    public static AtomicInteger num = new AtomicInteger(0);


    public static void main(String[] args) {
        Thread[] threads = new Thread[THREADS_CONUT];

        for (int i = 0; i < threads.length; i++) {
            threads[i] = new Thread(new Runnable() {
                @Override
                public void run() {
                    // 此處設置10000.過小看不到效果。請酌情設置
                    for (int j = 1; j <=10000 ; j++) {
                        // 如想要看到結果請放開下行註釋
                        //System.out.println(Thread.currentThread().getName() +" num = "+num);
                        num.incrementAndGet();
                    }
                }
            });
            threads[i].start();
        }

        while (Thread.activeCount() > 2) {
            Thread.yield();
        }
        System.out.println(num);
    }
}

結果是無論怎麼運行結果都和預期下相同。運行結果以下圖:

在這裏插入圖片描述

五、 Volatile能夠保證變量原子性嗎?

​ 咱們先來看一下下面兩行代碼

private volatile long num = 4642761357212574643L;

private volatile double amt= 4642761357212574643.23165421354;

如上代碼並不能保證num以及amt兩個變量就是原子性的,在32位處理器中 哪怕是經過volatile關鍵字進行修飾也沒法保證變量原子性。由於在32位系統下。若是出現了多線程同時操做某個變量。這個變量正在被線程a進行修改。此時線程b訪問此變量。可能只獲取到該變量的前32位,故可能會致使原子性失效。致使不可預知的狀況以及錯誤。若是本地和生產均爲64位處理器。請忽略以上廢話。

喜歡就關注我吧

在這裏插入圖片描述

相關文章
相關標籤/搜索