用CAS实现volatile原子性方式简介

当线程用synchronize锁的时候,可以保证线程是具有原子性 可见性 有序性的。

 

原子性,

表现为每个可以单独操作,不互相依赖,在线程中表现为每个线程都有所以它自己的一份copy值,不定期的刷新到主内存。(如果有锁,ulock时刷新到主内存)

而volatile变量不具有原子性,每次读写都是自己去主内存读主内存的值,也真是由于此种原因不能进行计数器操作,例如:

volatile i =1;

线程A,线程B 同时 i++;

i++ 即

i=i; //从主内存中读   1

i+1; //通过获取的值。计算 2

i=i+1; //把计算的值写入主内存中 3

 

当线程执行顺序如下时 A1 – >B1—>A2—>A3—>A1—>B2—>B3, 最后结果导致运行了两次结果还是2

 

对此,

1, 可以用CAS算法进行改进

CAS也可成为乐观锁,实现原理,通过保存原有值进行比较结果,直到更改成功

实现原理,CAS保存了3个值 H当前值(作为预期值),V内存值,S计算值

代码实现如下

public final int casTest() {
        for (;;) {
            int h=i;                  //A线程叫AH,B线程描述为BH        1
            int s = i + 1;         // A线程叫AS,B线程描述为BS         2

             if(h==i){           // 比较内存值和预期值                           3

               i=s;                  // 如果相同,赋值,成功CAS              4

              break;

            }
            }

 

A1 (A开始时用AH保存内存中此时的i值)->

B1(B开始时也用BH保存当前i值)->

A2  (把计算值2赋给AS)

A3(比较保存的AH和读取内存值AV,都是等于1,未改变)

A4(所以CAS成功,把AS即2放入内存中)

B2(把计算值2赋给BS)

B3(比较BH和读取当前内存值BV,BH是1,BV是2,所以不相等,返回到B1)

B1   (故重新取出内存值i,重复计算,此时BH=BV=2,BS=3赋给主内存,完成计数)

 

 

其实在并发包中的实现原理我也差不多(待考证……),只是用的是native方法,看代码

/**
* Atomically sets to the given value and returns the old value.
*
* @param newValue the new value
* @return the previous value
*/
public final int getAndSet(int newValue) {
    for (;;) {
        int current = get();   // step 1
        if (compareAndSet(current, newValue)) //step 2
            return current;
    }
}

step1 相当于获取当前值h,并保存

step2  newValue相当于比较s,计算值

 

 

2, 当然可以用synchronize锁进行同步(略)

posted @ 2013-03-12 00:45  何锦彬  阅读(4915)  评论(0编辑  收藏  举报