• 用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锁进行同步(略)

  • 相关阅读:
    Ubuntu下的解压缩
    Android开机动画
    Android 5.0源码编译问题
    ubuntu学习的简单笔记
    全局变量:global与$GLOBALS的区别和使用
    Java语言中的面向对象特性总结
    c/c++常见面试题
    查数据库中的表,了解大体结构
    PHP数组详解
    HTML5新增及移除的元素
  • 原文地址:https://www.cnblogs.com/springsource/p/2954920.html
Copyright © 2020-2023  润新知