zoukankan      html  css  js  c++  java
  • 乐观锁--CAS(Compare and swap)算法以及ABA问题

    1.首先做一个测试:i++。输出结果为10,因为在底层实现的时候会引入一个临时变量具体为:

     1 public static void main(String[] args) {
     2         //i++测试:
     3         int i=10;
     4         i=i++;
     5         System.out.println(i);
     6         /*
     7         *底层原理:
     8         _temp = i ;
     9         i = i + 1 ;
    10         i = _temp ;
    11         * */
    12     }

    所以i++就是一个非原子性操作,采用多线程再次测试:测试结果中会因为i++的非原子性操作带来读写不一致问题。比如:1,3,2,2,4,5,6,7,8,9序列的出现。两个2的出现就说明了,两个线程在同时从主存中读取,和进行加一操作时出现的不一致问题,那么可以用Volatile来解决这个不一致问题吗?不行。因为,这是一个非原子性操作。

    volatile变量具有 有序性(防止指令重排序),可见性(对数据的写操作直接写到内存中),不具有原子性。

     1 public class TestAtomicDemo {
     2     public static void main(String[] args) {
     3 
     4         Testi testi = new Testi();
     5 
     6         for (int i = 0; i < 10; i++) {
     7             new Thread(testi, String.valueOf(i)).start();
     8         }
     9     }
    10 }
    11 class Testi implements Runnable{
    12     int a=1;
    13     @Override
    14     public void run() {
    15         try {
    16             Thread.sleep(1000);
    17         } catch (InterruptedException e) {
    18             e.printStackTrace();
    19         }
    20         System.out.println(Thread.currentThread().getName()+": "+getA());
    21     }
    22     public int getA() {
    23         return a++;    
    24     }
    25 }

    2.Java并发包(java.util.concurrent)的主要实现机制:

    采用Volatile保证内存的可见性;

    采用CAS(Compare And Swap)算法保证数据的原子性。

    3.乐观锁(CAS算法)和悲观锁(synchronized):

    Synchronized就是一种悲观锁,因为它总是假设最坏的情况,每次去拿数据都会认为别人会修该,所以每次都会加锁,效率较低。

    乐观锁其实是一种思想,它具体有两个步骤:冲突检测和数据更新。所以它不会每次访问都进行加锁控制,只是在进行更新操作时才进行冲突检测和数据更新,适合用于读操作较多的程序,因此大大提高了吞吐量。其实现方式比较典型的就是CAS算法。当多个线程同时更新同一个变量时,只会有一个线程成功修改,其他的都会失败,更新失败的线程不会被挂起,而是被告知在这次竞争中失败了,并可以再次尝试。

    4.CAS(Compare And Swap)原理: 

    首先涉及三个操作数:

    内存值(V)--->首次读取内存中的值;

    预估值(A)--->再一次读取的内存中的值;

    更新值(B)--->新值;

    每次在进行更新操作时,当且仅当V==A(内存值和预期值相等时),后 V=B(将内存值更新为B),否则不进行任何操作。

    CAS是一种非阻塞算法的常见实现,JUC性能因此大大提升。

     1 //模拟CAS算法:
     2 public class TestCAS {
     3     public static void main(String[] args) {
     4         Cas cas = new Cas(10);
     5         for (int i = 0; i < 10; i++) {
     6             new Thread(() -> {
     7                 //10个线程都进行对数据的更新操作
     8                 int expectedValue = cas.getValue();  //更新前获得预期值
     9                 boolean b = cas.CompareTest(expectedValue, (int) Math.random());
    10                 System.out.println(b);
    11 
    12             }).start();
    13         }
    14     }
    15 }
    16 class Cas{
    17     /*
    18     * 内存值;预期值;新值。
    19     * */
    20 
    21     int value;  //内存值
    22 
    23     public synchronized int getValue() {
    24         return value;
    25     }
    26 
    27     public Cas(int value) {   //构造方法
    28         this.value = value;
    29     }
    30 
    31     //比较交换,并将内存值返回
    32     public int CompareSwap(int expectedValue,int newValue){
    33         int oldValue=value;  //获得内存值
    34         if(oldValue==expectedValue){
    35             value=newValue;
    36         }
    37         return oldValue;
    38     }
    39 
    40     //检测是否更新成功
    41     public boolean CompareTest(int expectedValue,int newValue){
    42         boolean flag=false;
    43         if(expectedValue==CompareSwap(expectedValue,newValue)){
    44             //判断预期值和内存值是否相等->更新是否成功
    45             flag=true;
    46         }
    47         return flag;
    48     }
    49 }

    CAS算法的ABA问题(当前线程的CAS操作无法分辨,值是否已经发生过变化):解决方法->在修改值的同时增加一个时间戳,只有当预期值和时间戳都相同时才进行修改。

     

    
    
  • 相关阅读:
    一个日期类型接口参数的构造思路
    python接口测试:如何将A接口的返回值传递给B接口
    关于查询类接口的一些总结
    (六十八)c#Winform自定义控件-DEMO整理-HZHControls
    (六十七)c#Winform自定义控件-柱状图-HZHControls
    (六十六)c#Winform自定义控件-图标-HZHControls
    (六十五)c#Winform自定义控件-思维导图/组织架构图(工业)-HZHControls
    (六十四)c#Winform自定义控件-温度计(工业)-HZHControls
    (六十三)c#Winform自定义控件-箭头(工业)-HZHControls
    (六十二)c#Winform自定义控件-警灯(工业)-HZHControls
  • 原文地址:https://www.cnblogs.com/xbfchder/p/11040550.html
Copyright © 2011-2022 走看看