91名师指路-头部
91名师指路

ABA问题的演示和解决方案

由于某些原因,现在不支持支付宝支付,如需要购买源码请加博主微信进行购买,微信号:13248254750

ABA问题的名词解释:


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

联系博主    
用户登录遮罩层
x

账号登录

91名师指路-底部