i++的原子性問題


一、什么是原子性

  簡單的可以理解為:操作是不可再分割的,比如;

int i=0;

但是i++的操作是可以再分的,比如:

i++ 
//分解后
i=i+i

上面的代碼在多線程環境下取值是有問題的,比如:

package com.example.demo.juc;

/**
 * @author DUCHONG
 * @since 2019-01-07 19:11
 **/
public class AtomicTest {

    public static void main(String[] args) {

        AtomicThread atomicTest=new AtomicThread();
        for (int i=1;i<=20;i++){

            new Thread(atomicTest).start();
        }
    }
}

class AtomicThread implements Runnable {

    private  int num=1;
    @Override
    public void run() {
        try {
            Thread.sleep(300);
            System.out.println(getNum());
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public int getNum(){
        return num++;
    }
}

結果:

這種問題當然可以通過加synchronized 關鍵字來解決,那有沒有另外一種方案呢,答案肯定是有的,且在jdk1.5的時候就有了,那就是Atomic包下的原子類

優化后:

package com.example.demo.juc;

import java.util.concurrent.atomic.AtomicInteger;

/**
 * @author DUCHONG
 * @since 2019-01-07 19:11
 **/
public class AtomicTest {

    public static void main(String[] args) {

        AtomicThread atomicTest=new AtomicThread();
        for (int i=1;i<=20;i++){

            new Thread(atomicTest).start();
        }
    }
}

class AtomicThread implements Runnable {

    private AtomicInteger at=new AtomicInteger(1);
    @Override
    public void run() {
        try {
            Thread.sleep(300);
            System.out.println(getNum());
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public int getNum(){
        return at.getAndIncrement();
    }
}

看源碼:

構造函數中的值,是volatile類型的

自增或者自減時,使用了CAS算法,CAS算法有三個操作數:

內存值:A

預估值:B

新值:V 

當且僅當 A=B 是 A=V 

否則不做任何操作。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM