java中Atomic变量的实现原理是怎么样的( 三 )
2.1原子变量类使用既然我们上面也说到了,使用Synchronized锁有点小题大作了,我们用原子变量类来改一下:class Count{ // 共享变量(使用AtomicInteger来替代Synchronized锁) private AtomicInteger count = new AtomicInteger(0); public Integer getCount() { return count.get(); } public void increase() { count.incrementAndGet(); }}// Main方法还是如上修改完,无论执行多少次,我们的结果永远是100!
其实Atomic包下原子类的使用方式都不会差太多,了解原子类各种类型,看看API,基本就会用了(网上也写得比较详细,所以我这里果断偷懒了)...
2.2ABA问题使用CAS有个缺点就是ABA的问题,什么是ABA问题呢?首先我用文字描述一下:
现在我有一个变量count=10,现在有三个线程,分别为A、B、C线程A和线程C同时读到count变量,所以线程A和线程C的内存值和预期值都为10此时线程A使用CAS将count值修改成100修改完后,就在这时,线程B进来了,读取得到count的值为100(内存值和预期值都是100),将count值修改成10线程C拿到执行权,发现内存值是10,预期值也是10,将count值修改成11上面的操作都可以正常执行完的,这样会发生什么问题呢??线程C无法得知线程A和线程B修改过的count值,这样是有风险的。
下面我再画个图来说明一下ABA的问题(以链表为例):
2.3解决ABA问题要解决ABA的问题,我们可以使用JDK给我们提供的AtomicStampedReference和AtomicMarkableReference类。
AtomicStampedReference:
An {@code AtomicStampedReference} maintains an object referencealong with an integer "stamp", that can be updated atomically.简单来说就是在给为这个对象提供了一个版本,并且这个版本如果被修改了,是自动更新的。
原理大概就是:维护了一个Pair对象,Pair对象存储我们的对象引用和一个stamp值。每次CAS比较的是两个Pair对象// Pair对象 private static class Pair\u0026lt;T\u0026gt; { final T reference; final int stamp; private Pair(T reference, int stamp) { this.reference = reference; this.stamp = stamp; } static \u0026lt;T\u0026gt; Pair\u0026lt;T\u0026gt; of(T reference, int stamp) { return new Pair\u0026lt;T\u0026gt;(reference, stamp); } } private volatile Pair\u0026lt;V\u0026gt; pair; // 比较的是Pari对象 public boolean compareAndSet(V expectedReference, V newReference, int expectedStamp, int newStamp) { Pair\u0026lt;V\u0026gt; current = pair; return expectedReference == current.reference \u0026amp;\u0026amp; expectedStamp == current.stamp \u0026amp;\u0026amp; ((newReference == current.reference \u0026amp;\u0026amp; newStamp == current.stamp) || casPair(current, Pair.of(newReference, newStamp))); }因为多了一个版本号比较,所以就不会存在ABA的问题了。
2.4LongAdder性能比AtomicLong要好如果是 JDK8,推荐使用 LongAdder 对象,比 AtomicLong 性能更好(减少乐观锁的重试次数)。去查阅了一些博客和资料,大概的意思就是:
推荐阅读
- dart这编程语言现在发展怎么样了,语法与Java,c#很相似,甚至更简洁
- Java工程师和C++工程师在工作上有啥区别哪个更适合自身发展
- 27岁,转行java的血与泪,该何去何从
- 怎样统计工程中未使用的java类
- 新互联网网站用Java还靠谱么对比Php,Python,Ruby的话
- 我想学java和安卓软件开发?
- 学计算机专业,java那些和网站开发选台式还是笔记本好
- JAVA设计思路
- 本人大专毕业一年,想要去培训,定了JAVAEE和安卓两个方向,应该学那个纠结,求帮助
- 从未接触过软件测试和java,可以学习主要是自学这两种其一吗
