★
上一篇文章介绍了CAS,其中谈到CAS会遇到ABA问题,那JAVA代码中是如何避免ABA问题的呢?下文就举两个例子说明
”
1.AtomicStampedReference的使用例子
Test.java
package com.zengame.FishReqTestTool;
import java.util.concurrent.atomic.AtomicStampedReference;
public class Test {
public static void main(String[] args) {
// https://my.oschina.net/senman/blog/3215704/print
Counter count = new Counter();
count.increment();
count.increment();
System.out.println(count.getCount());
count.decrement();
System.out.println(count.getCount());
}
}
class Counter {
private AtomicStampedReference count = new AtomicStampedReference(0, 0);
public int getCount() {
return count.getReference();
}
public int increment() {
int[] stamp = new int[1];
while (true) {
Integer value = count.get(stamp); // 同时获取时间戳和数据,防止获取到数据和版本不是一致的
int newValue = value + 1;
boolean writeOk = count.compareAndSet(value, newValue, stamp[0], stamp[0] + 1);
if (writeOk) {
return newValue;
}
}
}
public int decrement() {
int[] stamp = new int[1];
while (true) {
Integer value = count.get(stamp);// 同时获取时间戳和数据,防止获取到数据和版本不是一致的
int newValue = value - 1;
boolean writeOk = count.compareAndSet(value, newValue, stamp[0], stamp[0] + 1);
if (writeOk) {
return newValue;
}
}
}
}
class Count2 {
private AtomicStampedReference count = new AtomicStampedReference(0, 0);
public int getCount() {
return count.getReference();
}
public int increment() {
while (true) {
// 必须先获取stamp,然后取值,顺序不能反,否则仍然会有ABA的问题
int stamp = count.getStamp();
Integer value = count.getReference();
int newValue = value + 1;
boolean writeOk = count.compareAndSet(value, newValue, stamp, stamp + 1);
if (writeOk) {
return newValue;
}
}
}
public int decrement() {
while (true) {
// 必须先获取stamp,然后取值,顺序不能反,否则仍然会有ABA的问题
int stamp = count.getStamp();
Integer value = count.getReference();
int newValue = value - 1;
boolean writeOk = count.compareAndSet(value, newValue, stamp, stamp + 1);
if (writeOk) {
return newValue;
}
}
}
}
2.参考博客地址