aba问题的后果_aba行为原理

aba问题的后果_aba行为原理什么是ABA问题 在CAS算法中,需要取出内存中某时刻的数据(由用户完成),在下一时刻比较并交换(CPU保证原子操作),这个时间差会导致数据的变化。 1、线程1从内存位置V中取出A2、线程2从内存位置V中取出A3、线程2进行了写操作,将B写入内存位置V4、线程2将A再次写入内存位置V5、线程1进行C

aba问题的后果_aba行为原理"

什么是ABA问题

在CAS算法中,需要取出内存中某时刻的数据(由用户完成),在下一时刻比较并交换(CPU保证原子操作),这个时间差会导致数据的变化。

1、线程1从内存位置V中取出A
2、线程2从内存位置V中取出A
3、线程2进行了写操作,将B写入内存位置V
4、线程2将A再次写入内存位置V
5、线程1进行CAS操作,发现V中仍然是A,交换成功

尽管线程1的CAS操作成功,但线程1并不知道内存位置V的数据发生过改变

ABA问题本质:

根本在于CAS在修改变量的时候,无法记录变量的状态,比如是否修改过这个变量,修改的次数。

public class ABADemo {
    
    private static AtomicReference<Integer> atomicReference = new AtomicReference<Integer>(100);

    public static void main(String[] args) {
        new Thread(() -> {
            Integer a = atomicReference.get();
            atomicReference.compareAndSet(a, 101);
            atomicReference.compareAndSet(101, a);
            System.out.println("t1修改了atomicReference的值");
        },"t1").start();
        
        new Thread(() -> {
            Integer b = atomicReference.get();
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            System.out.println(atomicReference.compareAndSet(b, 2019) + "\t修改后的值:" + atomicReference.get());
        },"t2").start();
    }
}

 

 ABA问题怎么解决

public class AtomicStampedReferenceTest {
    
    private static AtomicStampedReference<Integer> atomicStampedReference = new AtomicStampedReference<Integer>(100,1);

    public static void main(String[] args) {
        new Thread(() -> {
            Integer stamp = atomicStampedReference.getStamp();
            System.out.println("t1拿到的初始版本号:"  + stamp);
            //睡眠1秒,是为了让t2线程也拿到同样的初始版本号
            try {
               Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            atomicStampedReference.compareAndSet(100, 101,stamp,stamp+1);
            stamp = atomicStampedReference.getStamp();
            atomicStampedReference.compareAndSet(101, 100,stamp,stamp+1);
        },"t1").start();
        
        new Thread(() -> {
            int stamp = atomicStampedReference.getStamp();
            System.out.println("t2拿到的初始版本号:" + stamp);
            //睡眠3秒,是为了让t1线程完成ABA操作
            try {
                Thread.sleep(3000);
             } catch (InterruptedException e) {
                 e.printStackTrace();
             }
            System.out.println("最新版本号:" + atomicStampedReference.getStamp());
            System.out.println(atomicStampedReference.compareAndSet(100, 2019,stamp,atomicStampedReference.getStamp() + 1) + "\t当前 值:" + atomicStampedReference.getReference());
        },"t2").start();
    }
}

 

如果不关心引用变量更改了几次,只单纯的关心是否更改过,可以使用AtomicMarkableReference

public class ABADemo {
    
    private static AtomicMarkableReference<Integer> atomicMarkableReference = new AtomicMarkableReference<Integer>(100,false);

    public static void main(String[] args) {
        new Thread(() -> {
            System.out.println("t1版本号是否被更改:" + atomicMarkableReference.isMarked());
            //睡眠1秒,是为了让t2线程也拿到同样的初始版本号
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            atomicMarkableReference.compareAndSet(100, 101,false,true);
          
        },"t1").start();
        
        new Thread(() -> {
            boolean isMarked = atomicMarkableReference.isMarked();
            System.out.println("t2版本号是否被更改:" + isMarked);
            //睡眠3秒,是为了让t1线程执行
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("是否更改过:" + atomicMarkableReference.isMarked());
            System.out.println(atomicMarkableReference.compareAndSet(100, 2019,isMarked,true) + "\t当前 值:" + atomicMarkableReference.getReference());
        },"t2").start();
    }
}

 

今天的文章aba问题的后果_aba行为原理分享到此就结束了,感谢您的阅读,如果确实帮到您,您可以动动手指转发给其他人。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/47237.html

(0)
编程小号编程小号
上一篇 2023-09-04 23:17
下一篇 2023-09-04

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注