原 ABA问题的演示和解决方案
版权声明:本文为博主原创文章,请尊重他人的劳动成果,转载请附上原文出处链接和本声明。
本文链接:https://www.91mszl.com/zhangwuji/article/details/1129
ABA问题具体是什么意思,如下图所示。
假设我们主内存的值为100,线程T1和T2在初始状态下,都会拷贝一个副本到自己的工作内存中,即T1和T2都是100,T1执行完需要10秒钟,T2执行完需要2秒钟,假设T2先将100改为了80,然后和主内存进行比较发现没有被改动,于是更改主内存的值为80,然后T2在将80改为了60,T2在由60改为100,T2更改完成后,假设T1此时执行完成了,将自己工作内存的值100和主内存的值100进行比较,发现没有被改过。这种现象就是ABA问题。
ABA问题的代码演示如下:
package com.mszl.thread;
import java.util.concurrent.atomic.AtomicReference;
/**
* 功能:ABA问题的演示
* 备注:更多资料请访问 http://www.91mszl.com
* @author bobo teacher
*/
public class ABADemo {
static AtomicReference<Integer> rf=new AtomicReference<Integer>(100);
public static void main(String[] args) {
// t1 线程
Thread t1=new Thread(new Runnable() {
@Override
public void run() {
rf.compareAndSet(100, 108); // 将值由100更改为108
System.out.println(Thread.currentThread().getName() + " 当前的值为:" + rf.get());
rf.compareAndSet(108, 100); // 将值由108更改为100
System.out.println(Thread.currentThread().getName() + " 当前的值为:" + rf.get());
}
});
t1.start();
// t2线程
Thread t2=new Thread(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
boolean flag=rf.compareAndSet(100, 888); // t2 将值更改为888
System.out.println(flag + "\t" + Thread.currentThread().getName() + " 当前的值为:" + rf.get());
}
});
t2.start();
}
}
ABA问题的解决方案。AtomicStampedReference
代码如下图所示:
package com.mszl.thread;
import java.util.concurrent.atomic.AtomicStampedReference;
/**
* 功能:ABA问题的解决方案
* 备注:更多资料请访问 http://www.91mszl.com
* @author bobo teacher
*/
public class ABADemo1 {
static AtomicStampedReference<Integer> stampRf=new AtomicStampedReference<Integer>(100, 1);
public static void main(String[] args) {
// t1 线程
Thread t1=new Thread(new Runnable() {
@Override
public void run() {
int sp=stampRf.getStamp(); // 获取到当前的版本号
System.out.println(Thread.currentThread().getName() + "\t 第一次版本号" + sp);
try {
Thread.sleep(1000); // 保证t2线程拿到版本号
} catch (InterruptedException e) {
e.printStackTrace();
}
stampRf.compareAndSet(100, 108, stampRf.getStamp(), stampRf.getStamp()+1); // 将值由100改为108
System.out.println(Thread.currentThread().getName() + "\t 当前的值" + stampRf.getReference() + "\t 版本号:" + stampRf.getStamp());
stampRf.compareAndSet(108, 100, stampRf.getStamp(), stampRf.getStamp()+1); // 将值由100改为108
System.out.println(Thread.currentThread().getName() + "\t 当前的值" + stampRf.getReference() + "\t 版本号:" + stampRf.getStamp());
}
});
t1.start();
// t2线程
Thread t2=new Thread(new Runnable() {
@Override
public void run() {
int sp=stampRf.getStamp(); // 获取到当前的版本号
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
boolean flag=stampRf.compareAndSet(100, 999, sp, sp+1); // 将值由100改为999
System.out.println(Thread.currentThread().getName() + "\t 是否修改成功:" + flag + "\t 当前最新版本号" + stampRf.getStamp());
}
});
t2.start();
}
}
执行结果:
Thread-0 第一次版本号1
Thread-0 当前的值108 版本号:2
Thread-0 当前的值100 版本号:3
Thread-1 是否修改成功:false 当前最新版本号3
2019-11-25 15:15:47 阅读(1211)
名师出品,必属精品 https://www.91mszl.com
博主信息