zoukankan      html  css  js  c++  java
  • java并发:CAS算法和ABA问题

    CAS算法是硬件对于并发的支持,针对多处理器操作而设计的处理器中的一种特殊指令。

    CAS用于管理对共享数据的并发访问。

    java的并发包中,AQS、原子操作类等都是基于CAS实现的。

    CAS 是一种 无锁的 非阻塞算法的 实现。

    CAS(Compare-And-Swap),简单来说就是比较和替换。

    比较和替换是使用一个期望值和一个变量的当前值进行比较,如果当前变量的值与我们期望的值相等,就使用一个新值替换当前变量的值。

    比如说,想使用一台机器,先通过比较判断这台机器是否处于未占用状态,如果机器处于未占用状态,就将它设为使用状态。


    CAS 包含了三个操作数:
    需要读写的内存值: V,进行比较的预估值: A,拟写入的更新值: B。
    当且仅当 V == A 时, V = B, 否则,将不做任何操作;

    以下用同步锁synchronized模拟CAS 算法。

    注意:真正的CAS算法是无锁的。

    如下:

    public class CasDemo {
        public static void main(String[] args) {
            final CompareAndSwap cas = new CompareAndSwap();
    
            for(int i=0; i<10; i++){
                // 创建10个线程,模拟多线程环境
                new Thread(new Runnable(){
                    @Override
                    public void run(){
                        int expectedValue = cas.get();
    
                        boolean b = cas.compareAndSwap(expectedValue, (int)(Math.random()*5));
                    }
                }).start();
            }
        }
    
    
        static   class  CompareAndSwap{
             private  int value;
    
            // 获取内存值
             public synchronized  int get() {
                 return  value;
             }
    
             // 比较当前值和期望值,相同就替换。
             public  synchronized  boolean compareAndSwap(int expectedValue,int newValue) {
                 //获取旧值
                 int oldValue=value;
                 if(oldValue==expectedValue) {
                        this.value=newValue;
                        System.out.println(Thread.currentThread().getName()+"比较当前值和期望值,结果一致,将其替换为新值。");
                        return true;
                 }
                 System.out.println(Thread.currentThread().getName()+"比较当前值和期望值,结果不一致,不替换为新值");
                 return  false;
             }
        }
    }

    ABA问题:

    尽管CAS看起来没问题,其实存在一个逻辑漏洞。

    如果一个变量V初次读取时是A值,并且在赋值时检查到它仍然是A值,那么我们就能说它的值没有改变过吗?

    如果在此期间,它的值曾经改成了B,后来又改回为A。那么CAS操作就会误以为它从来没有改变过。

    这个称为CAS的“ABA”问题。

    当然,在大部分情况下ABA问题并不会影响程序并发的正确性。如果需要解决ABA问题,可以改用传统的互斥同步。

  • 相关阅读:
    ruby 类库组成
    ruby 数据类型Number
    ruby require的使用
    ruby $LOAD_PATH及类加载
    ruby编码说明
    RubyMine常用快捷键
    基础
    基础
    基础
    基础
  • 原文地址:https://www.cnblogs.com/expiator/p/9450264.html
Copyright © 2011-2022 走看看