ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

ABA问题

2022-02-20 16:04:46  阅读:142  来源: 互联网

标签:ABA Thread System 问题 println atomicStampedReference atomicReference out


ABA问题

  • AtomicInteger

CAS --> UnSafe --> CAS底层思想 --> ABA -->原子引用更新 -->如何规避ABA问题

1.介绍

1.1图解

  • 所以,当A线程工作完成进行CAS时,预期值为A,真实值也为A,线程A会认为主物理内存中的值没有线程更改过,直接将其值写回主物理内存。
  • 实际上只是首尾相同,中间可能有很多次变更

1.2演示

import java.util.concurrent.atomic.AtomicReference;

public class ABADemo {
    static AtomicReference<Integer> atomicReference= new AtomicReference<>(100);
    public static  void main(String[] args){
        new Thread(() ->{
            atomicReference.compareAndSet(100, 101);
            atomicReference.compareAndSet(101, 100);
        },"t1").start();
        new Thread(() ->{
            //暂停1s,保证t1完成了一次ABA操作
            try{
                TimeUnit.SECONDS.sleep(1);
            }catch (InterruptedException e){
                e.printStackTrace();
            }
            System.out.println( atomicReference.compareAndSet(100, 2019)+"\t"+atomicReference.get());

        },"t2").start();
    }
}

2. 如何解决ABA问题

2.1 原子引用

import java.util.concurrent.atomic.AtomicReference;
class User{
    String userName;
    int age;

    public User(String userName, int age) {
        this.userName = userName;
        this.age = age;
    }

    @Override
    public String toString() {
        return "User{" +
                "userName='" + userName + '\'' +
                ", age=" + age +
                '}';
    }
}
public class AtomicReferenceDemo {
    public static void main(String[] args){
        AtomicReference<User> atomicReference = new AtomicReference<>();
        User z3 = new User("z3",22);
        User l4 = new User("l4",25);
        atomicReference.set(z3);
        System.out.println(atomicReference.compareAndSet(z3, l4)+"\t"+atomicReference.get().toString());
        System.out.println(atomicReference.compareAndSet(z3, l4)+"\t"+atomicReference.get().toString());
    }
}

2.2时间戳原子引用

//AtomicStampeReference
public class ABADemo {
    static AtomicReference<Integer> atomicReference= new AtomicReference<>(100);
    static AtomicStampedReference<Integer> atomicStampedReference = new AtomicStampedReference<Integer>(100, 1);
    public static  void main(String[] args){
        new Thread(() ->{
            int stamp = atomicStampedReference.getStamp();
            System.out.println(Thread.currentThread().getName()+"\t第一次版本号"+stamp);
            try{
                TimeUnit.SECONDS.sleep(1);
            }catch (InterruptedException e){
                e.printStackTrace();}
            atomicStampedReference.compareAndSet(100,12,atomicStampedReference.getStamp(),atomicStampedReference.getStamp()+1);
            System.out.println(Thread.currentThread().getName()+"\t第二次版本号"+atomicStampedReference.getStamp());
            System.out.println(Thread.currentThread().getName()+"\t当前值"+atomicStampedReference.getReference());
            System.out.println(atomicStampedReference.compareAndSet(12,100,atomicStampedReference.getStamp(),atomicStampedReference.getStamp()+1));
            System.out.println(Thread.currentThread().getName()+"\t第三次版本号"+atomicStampedReference.getStamp());
        },"t3").start();
        new Thread(() ->{
            int stamp = atomicStampedReference.getStamp();
            System.out.println(Thread.currentThread().getName()+"\t第一次版本号"+stamp);
            try{
                TimeUnit.SECONDS.sleep(5);
            }catch (InterruptedException e){
                e.printStackTrace();
            }
            boolean result = atomicStampedReference.compareAndSet(100,101,stamp,stamp+1);
            System.out.println(Thread.currentThread().getName()+"\t修改"+result+"\t当前版本号"+atomicStampedReference.getStamp());
            System.out.println(Thread.currentThread().getName()+"\t当前值"+atomicStampedReference.getReference());
        },"t4").start();
    }
}

3.问题

  1. 当CAS传入的新值大于等于128的时候一直修改失败

    原因:Integer对-128~127间的数字有缓存,所以在此区间的current==expectedReference为true,当current>127,每次装箱将返回新的Integer对象,此时current!=expectedReference导致compareAndSet一直返回false。

标签:ABA,Thread,System,问题,println,atomicStampedReference,atomicReference,out
来源: https://www.cnblogs.com/ftfty/p/15915615.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有