原创

JAVA锁体系之CAS的ABA问题AtomicStampedReference使用

上一篇文章介绍了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<Integer> count = new AtomicStampedReference<Integer>(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<Integer> count = new AtomicStampedReference<Integer>(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.参考博客地址

参考博客地址

正文到此结束