文档章节

java 原子类实现原理剖析

九州暮云
 九州暮云
发布于 2017/09/07 22:35
字数 907
阅读 32
收藏 0

前言

在jdk中提供了一些java.util.concurrent.atomic原子操作类。对于原子类变量的操作是不会存在并发性问题的,不需要使用synchronized关键字进行并发控制。它底层自身的实现即可保证变量的可见性以及操作的原子性,一般我们可以使用AtomicInteger,AtomicLong等实现计数器等功能,利用AtomicBoolean实现标志位等功能。

使用示例

public class Message {
  // 实现一个id自增计数器
  private static AtomicLong count = new AtomicLong();
  //无需进行锁并发控制,防止id重复
  public Long getMsgId(){
    return count.getAndIncrement();
  }
}

原理剖析

一般实现线程安全的常见两种机制:

  • 加锁机制(常见synchronized和ReentrantLock等),特点:阻塞;

  • 无锁机制(常见无锁算法有:CAS算法),特点:非阻塞;

原子量底层的实现均是采用CAS非阻塞算法实现的,是无锁(lock-free)算法中最有名的一种(无锁算法:不使用锁机制来实现线程安全的算法,采用锁机制都会存在线程为请求锁而产生阻塞的情况),CAS不会阻塞线程从而不会带来CPU上下文切换的性能开销。

CAS非阻塞算法的原理

CAS的全称是Compare-And-Swap(意思是比较后交换):指当两者(这个两者是指线程栈内存中备份的变量值和主内存中共享变量值)进行比较时,如果值相等,则证明共享数据没有被其他线程修改过,则替换成新值,然后继续往下运行;如果不相等,说明主内存中的共享数据被其它线程修改过,放弃已经所做的操作,然后重新执行刚才的操作(可见CAS算法的关键就是这个循环体结构,退出循环的条件是主内存中的共享数据没有被其他线程修改过,如果被修改过,则该线程会重复执行此操作,直到满足退出循环体的条件为止,这也是为什么线程不会阻塞的原因)。容易看出 CAS 操作是基于共享数据不会被修改的假设,采用了类似于数据库的 commit-retry 的模式。当同步冲突出现的机会很少时,这种假设能带来较大的性能提升。

下面以jdk AtomicInteger类的具体实现为例,进行说明:

public class AtomicInteger extends Number implements java.io.Serializable {
    private static final longserialVersionUID = 6214790243416807050L;
    // setup to use Unsafe.compareAndSwapInt for updates
    private static final Unsafe unsafe = Unsafe.getUnsafe();
    
    private volatile int value;
    
    //value字段相对AtomicInteger对象内存地址的偏移量
    private static final longvalueOffset;
    static {
      try {
        valueOffset = unsafe.objectFieldOffset
            (AtomicInteger.class.getDeclaredField("value"));
      } catch (Exception ex) { thrownew Error(ex); }
    }
    
    //该AtomicInteger原子量对应的值value(共享变量)
    private volatile int value;
    
    //返回当前value
    public final int get() {
        return value;
    }
 
    //该方法的作用value++的线程安全版,返回自增长以前的值
    public final int getAndIncrement() {
        //CAS算法中循环体结构
        for (;;) {
            int current = get();
            int next = current + 1;
            //主内存变量更新成功,则退出循环体,否则重复执行此自增操作,直到更新成功为止
            if (compareAndSet(current, next))
                return current;//返回自增长以前的值
        }
    }
    //拿expect和主内存中的值进行比较,如果相等,说明主内存中的值没有发生过修改
   //则将新值写入到主内存,return true。否则直接return false;
   public final boolean compareAndSet(int expect, int update) {
      return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
   }
  
}

参考链接:

本文转载自:http://www.pandan.xyz/2016/08/27/java 原子类实现原理剖析/

共有 人打赏支持
九州暮云
粉丝 56
博文 140
码字总数 80876
作品 0
海淀
高级程序员
读书笔记之《Java并发编程的艺术》-并发编程容器和框架(重要)

读书笔记部分内容来源书出版书,版权归本书作者,如有错误,请指正。 欢迎star、fork,读书笔记系列会同步更新 git https://github.com/xuminwlt/j360-jdk module j360-jdk-thread/me.j360....

Hi徐敏
2015/11/11
0
1
sharding-jdbc源码分析—准备工作

原文作者:阿飞Javaer 原文链接:https://www.jianshu.com/p/7831817c1da8 接下来对sharding-jdbc源码的分析基于tag为源码,根据sharding-jdbc Features深入学习sharding-jdbc的几个主要特性...

飞哥-Javaer
05/03
0
0
ThreadLocal 类 的源码解析以及使用原理

1、原理图说明      首先看这一张图,我们可以看出,每一个Thread类中都存在一个属性 ThreadLocalMap 成员,该成员是一个map数据结构,map中是一个Entry的数组,存在entry实体,该实体包...

小勇DW3
08/13
0
0
Android--面试中遇到的问题总结(三)

《Android 开发工程师面试指南 LearningNotes 》,作者是陶程,由梁观全贡献部分。大家可以去知乎关注这两位用心的少年。这份指南包含了大部分Android开发的基础、进阶知识,不仅可以帮助准备...

sealin
2017/02/22
0
0
读书笔记之《Java并发编程的艺术》-线程池和Executor的子孙们

读书笔记部分内容来源书出版书,版权归本书作者,如有错误,请指正。 欢迎star、fork,读书笔记系列会同步更新 git https://github.com/xuminwlt/j360-jdk module j360-jdk-thread/me.j360....

Hi徐敏
2015/11/11
0
1

没有更多内容

加载失败,请刷新页面

加载更多

20180920 rzsz传输文件、用户和用户组相关配置文件与管理

利用rz、sz实现Linux与Windows互传文件 [root@centos01 ~]# yum install -y lrzsz # 安装工具sz test.txt # 弹出对话框,传递到选择的路径下rz # 回车后,会从对话框中选择对应的文件传递...

野雪球
今天
2
0
OSChina 周四乱弹 —— 毒蛇当辣条

Osc乱弹歌单(2018)请戳(这里) 【今日歌曲】 @ 达尔文:分享花澤香菜/前野智昭/小野大輔/井上喜久子的单曲《ミッション! 健?康?第?イチ》 《ミッション! 健?康?第?イチ》- 花澤香菜/前野智...

小小编辑
今天
8
3
java -jar运行内存设置

java -Xms64m #JVM启动时的初始堆大小 -Xmx128m #最大堆大小 -Xmn64m #年轻代的大小,其余的空间是老年代 -XX:MaxMetaspaceSize=128m # -XX:CompressedClassSpaceSize=6...

李玉长
今天
4
0
Spring | 手把手教你SSM最优雅的整合方式

HEY 本节主要内容为:基于Spring从0到1搭建一个web工程,适合初学者,Java初级开发者。欢迎与我交流。 MODULE 新建一个Maven工程。 不论你是什么工具,选这个就可以了,然后next,直至finis...

冯文议
今天
2
0
RxJS的另外四种实现方式(四)——性能最高的库(续)

接上一篇RxJS的另外四种实现方式(三)——性能最高的库 上一篇文章我展示了这个最高性能库的实现方法。下面我介绍一下这个性能提升的秘密。 首先,为了弄清楚Most库究竟为何如此快,我必须借...

一个灰
今天
3
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部