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

来源:互联网 发布:打印出库单软件 编辑:程序博客网 时间:2024/06/06 08:04

转载地址:http://blog.csdn.net/ustcxjt/article/details/7303784

先看一个使用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);
    }



0 0
原创粉丝点击