一、什么是原子性
简单的可以理解为:操作是不可再分割的,比如;
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
否则不做任何操作。