博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
(201)Atomic*实现原理
阅读量:6587 次
发布时间:2019-06-24

本文共 1922 字,大约阅读时间需要 6 分钟。

成神之路,需要耐得住寂寞,开启总结源码之旅。

我阅读总结源码的目的不是为了炫技,我希望通过阅读源码可以解决一些问题,也可以通过阅读源码理解别人思想,以帮助我们更好的写我们的代码。

引子

在多线程的场景中,我们需要如何同步数据,通常会使用synchronized或者lock来处理,使用了synchronized意味着内核态的一次切换。这是一个很重的操作。有没有一种方式,可以比较便利的实现一些简单的数据同步,比如计数器等等。concurrent包下的atomic提供我们这么一种轻量级的数据同步的选择。

他山之石

  • 说一说Java的Unsafe类:
  • java魔法之unsafe:
  • java乐观锁实现案例:
  • Java并发问题--乐观锁与悲观锁以及乐观锁的一种实现方式-CAS:
  • JDK8系列之LongAdder解析:
  • jdk1.8 LongAdder源码学习:

使用例子

import java.util.concurrent.CountDownLatch;import java.util.concurrent.atomic.AtomicInteger;public class App {    public static void main(String[] args) throws Exception {        CountDownLatch countDownLatch = new CountDownLatch(100);        AtomicInteger atomicInteger = new AtomicInteger(0);        for (int i = 0; i < 100; i++) {            new Thread() {                @Override                public void run() {                    atomicInteger.getAndIncrement();                    countDownLatch.countDown();                }            }.start();        }        countDownLatch.await();        System.out.println(atomicInteger.get());    }}复制代码

请暂时先忽略CountDownLatch,只是为了在主线程中等待所有子线程执行完,打印结果。这个结果永远都是100。如果将AtomicInteger换成Integer,打印结果基本都是小于100。

原理

我们可以看一下AtomicInteger的代码

他的值是存在一个volatile的int里面。volatile只能保证这个变量的可见性。不能保证他的原子性。

可以看看getAndIncrement这个类似i++的函数,可以发现,是调用了UnSafe中的getAndAddInt。

UnSafe是何方神圣?可以参考上面的文章了解一下,UnSafe提供了java可以直接操作底层的能力。 进一步,我们可以发现实现方式:

如何保证原子性:自旋 + CAS(乐观锁)。在这个过程中,通过compareAndSwapInt比较更新value值,如果更新失败,重新获取旧值,然后更新。

优缺点

CAS相对于其他锁,不会进行内核态操作,有着一些性能的提升。但同时引入自旋,当锁竞争较大的时候,自旋次数会增多。cpu资源会消耗很高。

换句话说,CAS+自旋适合使用在低并发有同步数据的应用场景。

jdk8做出的改进和努力

在jdk8中引入了4个新的计数器类型,LongAdder、LongAccumulator、DoubleAdder、DoubleAccumulator。他们都是继承于Striped64。

在LongAdder 与AtomicLong有什么区别? Atomic*遇到的问题是,只能运用于低并发场景。因此LongAddr在这基础上引入了分段锁的概念。可以参考《JDK8系列之LongAdder解析》一起看看做了什么。

大概就是当竞争不激烈的时候,所有线程都是通过CAS对同一个变量(Base)进行修改,当竞争激烈的时候,会将根据当前线程哈希到对于Cell上进行修改(多段锁)。

可以看到大概实现原理是:通过CAS乐观锁保证原子性,通过自旋保证当次修改的最终修改成功,通过**降低锁粒度(多段锁)**增加并发性能。

关键点

  • 自旋
  • CAS乐观锁
  • 多段锁(分治思想)

转载地址:http://krhno.baihongyu.com/

你可能感兴趣的文章
Uber提出基于Metropolis-Hastings算法的GAN改进思想
查看>>
独立云计算服务商的多维实践之道:用户需求驱动变革
查看>>
Spotify开源其Cassandra编排工具cstar
查看>>
css:transform,transition,animation总结
查看>>
理解BERT Transformer:Attention is not all you need!
查看>>
GCP发布Kaniko:在非特权容器和Kubernetes中构建容器镜像的工具
查看>>
华泰证券:如何自研高效可靠的交易系统通信框架?
查看>>
编程语言安全性排行榜:Ruby最佳,C语言漏洞最多?
查看>>
VS2015将于7月20日发布,所支持的C++特性已经完成
查看>>
EGO走进美团——追寻千亿市场背后的技术力量
查看>>
Docker加入裁员大军,关键时期Docker将何去何从?
查看>>
浏览器厂商开始默认支持WebAssembly格式
查看>>
Coolblue的持续部署
查看>>
无服务平台性能比较
查看>>
时序数据库InfluxDB 2.0 alpha 发布:主推新的Flux查询语言,TICK栈将成为整体
查看>>
OpsRamp推出以服务为中心的AIOps和云监控功能
查看>>
微服务:更愉快还是更嘈杂?
查看>>
GitLab容器注册服务已集成于Docker容器
查看>>
针对ASP.NET Core Web API的先进架构
查看>>
关于CSS一些细节问题
查看>>