java中Atomic变量的实现原理是怎么样的
写过一篇关于Atomic的基础文章,可以看看~如果有帮助,希望可以给我点个赞~
前言只有光头才能变强干货文章导航:https://github.com/ZhongFuCheng3y/3y在阅读《阿里巴巴 Java开发手册》读后感时,还有未解决的问题:
如果是count++操作,使用如下类实现: AtomicInteger count = new AtomicInteger(); count.addAndGet(1);如果是 JDK8,推荐使用 LongAdder 对象,比 AtomicLong 性能更好(减少乐观锁的重试次数)。之前在学习的时候也看过AtomicInteger类很多次了,一直没有去做相关的笔记。现在遇到问题了,于是就过来写写笔记,并希望在学习的过程中解决掉问题。
一、基础铺垫首先我们来个例子:public class AtomicMain { public static void main(String args) throws InterruptedException { ExecutorService service = Executors.newCachedThreadPool(); Count count = new Count(); // 100个线程对共享变量进行加1 for (int i = 0; i \u0026lt; 100; i++) { service.execute(() -\u0026gt; count.increase()); } // 等待上述的线程执行完 service.shutdown(); service.awaitTermination(1, TimeUnit.DAYS); System.out.println("公众号:Java3y---------"); System.out.println(count.getCount()); }}class Count{ // 共享变量 private Integer count = 0; public Integer getCount() { return count; } public void increase() { count++; }}你们猜猜得出的结果是多少?是100吗?
多运行几次可以发现:结果是不确定的,可能是95,也可能是98,也可能是100
根据结果我们得知:上面的代码是线程不安全的!如果线程安全的代码,多次执行的结果是一致的!
我们可以发现问题所在:count++并不是原子操作。因为count++需要经过读取-修改-写入三个步骤。举个例子:
如果某一个时刻:线程A读到count的值是10,线程B读到count的值也是10线程A对count++,此时count的值为11线程B对count++,此时count的值也是11(因为线程B读到的count是10)所以到这里应该知道为啥我们的结果是不确定了吧。要将上面的代码变成线程安全的(每次得出的结果是100),那也很简单,毕竟我们是学过synchronized锁的人:
在increase()加synchronized锁就好了public synchronized void increase() { count++;}无论执行多少次,得出的都是100:
从上面的代码我们也可以发现,只做一个++这么简单的操作,都用到了synchronized锁,未免有点小题大做了。
Synchronized锁是独占的,意味着如果有别的线程在执行,当前线程只能是等待!于是我们原子变量的类就登场了!
1.2CAS再来看看在写文章之前,本以为对CAS有一定的了解了(因为之前已经看过相关概念,以为自己理解了)..但真正敲起键盘写的时候,还是发现没完全弄懂...所以再来看看CAS吧。
来源维基百科:
比较并交换(compare and swap, CAS),是原子操作的一种,可用于在多线程编程中实现不被打断的数据交换操作,从而避免多线程同时改写某一数据时由于执行顺序不确定性以及中断的不可预知性产生的数据不一致问题。 该操作通过将内存中的值与指定数据进行比较,当数值一样时将内存中的数据替换为新的值。CAS有3个操作数:
推荐阅读
- dart这编程语言现在发展怎么样了,语法与Java,c#很相似,甚至更简洁
- Java工程师和C++工程师在工作上有啥区别哪个更适合自身发展
- 27岁,转行java的血与泪,该何去何从
- 怎样统计工程中未使用的java类
- 新互联网网站用Java还靠谱么对比Php,Python,Ruby的话
- 我想学java和安卓软件开发?
- 学计算机专业,java那些和网站开发选台式还是笔记本好
- JAVA设计思路
- 本人大专毕业一年,想要去培训,定了JAVAEE和安卓两个方向,应该学那个纠结,求帮助
- 从未接触过软件测试和java,可以学习主要是自学这两种其一吗
