CAS指令 incrementAndGet方法 JAVA非阻塞同步

来源:互联网 发布:寰宇人生软件下载 编辑:程序博客网 时间:2024/06/15 03:32

先看一个使用volatile的例子

 

public class VolatileTest {public static volatile int race=0;public static void increase(){race++;}private static final int THREADS_COUNT=20;public static void main(String[] args){Thread[] threads=new Thread[THREADS_COUNT];for(int i=0;i<THREADS_COUNT;i++){threads[i]=new Thread(new Runnable(){public void run(){for(int i=0;i<10000;i++){increase();}}});threads[i].start();}while(Thread.activeCount()>1)Thread.yield();System.out.println(race);}}


 

 

预期输出200000

但是实际输出总是小于200000

如148407

原因:volatile变量只能保证可见性

主要用于下列场景:

1、运算结果不依赖变量的当前值

2、变量不需要与其他变量共同参与不变约束

 

改进方法

使用CAS指令

CAS中有三个操作树,分别是内存位置V、旧的预期值A、新值B

当且仅当V符合A时,处理器才用B更新V

不论更新成功与否返回值均为V(更新前的值)

此指令的操作是原子操作

 

public class AtomicTest { public static AtomicInteger race = new AtomicInteger(0); public static void increase() {  race.incrementAndGet(); } private static final int THREADS_COUNT = 20; public static void main(String[] args) {  Thread[] threads = new Thread[THREADS_COUNT];  for (int i = 0; i < THREADS_COUNT; i++) {   threads[i] = new Thread(new Runnable() {    public void run() {     for (int i = 0; i < 10000; i++) {      increase();     }    }   });   threads[i].start();  }  while (Thread.activeCount() > 1)   Thread.yield();  System.out.println(race); }}


 

输出:200000

 

看下incrementAndGet的实现

/**     * Atomically increments by one the current value.     *     * @return the updated value     */    public final int incrementAndGet() {        for (;;) {            int current = get();            int next = current + 1;            if (compareAndSet(current, next))                return next;        }    }


再看下compareAndSet的实现

 /**     * Atomically sets the value to the given updated value     * if the current value {@code ==} the expected value.     *     * @param expect the expected value     * @param update the new value     * @return true if successful. False return indicates that     * the actual value was not equal to the expected value.     */    public final boolean compareAndSet(int expect, int update) {return unsafe.compareAndSwapInt(this, valueOffset, expect, update);    }


 

遗留问题:“ABA”问题

概率低,可以使用传统的互斥同步方法解决

 

 

参考:

深入理解Java虚拟机:JVM高级特性与最佳实践, 作者: 周志明, 品牌: 机械工业出版社, 版本: 第1版, 机械工业出版社

 

 

 

 

原创粉丝点击