文档章节

java 原子类实现原理剖析

九州暮云
 九州暮云
发布于 2017/09/07 22:35
字数 907
阅读 25
收藏 0
点赞 0
评论 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 原子类实现原理剖析/

共有 人打赏支持
九州暮云
粉丝 47
博文 132
码字总数 67325
作品 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
读书笔记之《Java并发编程的艺术》-线程池和Executor的子孙们

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

Hi徐敏
2015/11/11
0
1
Java开发者不会这些永远都只能是三流程序员,细数一下你是不是?

源码系列 手写spring mvc框架 基于Spring JDBC手写ORM框架 实现自己的MyBatis Spring AOP实战之源码分析 Spring IOC高级特性应用分析 ORM框架底层实现原理剖析 手写Spring MVC框架实现 手把手...

美的让人心动
04/16
0
0
读书笔记之《Java并发编程的艺术》-并发编程基础

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

Hi徐敏
2015/11/11
0
8
ThreadLocal的那些事儿

什么是ThreadLocal? 顾名思义它是local variable(线程局部变量)。 它的功用非常简单,就是为每一个使用该变量的线程都提供一个变量值的副本,是每一个线程都可以独立地改变自己的副本,而...

陶邦仁
2012/09/07
0
2
2018年Java编程学习面试最全知识点总结

Java是一种可以撰写跨平台应用软件的面向对象的程序设计语言。Java 技术具有卓越的通用性、高效性、平台移植性和安全性,广泛应用于PC、数据中心、游戏控制台、科学超级计算机、移动电话和互...

Java小辰
05/14
0
0
阿里历年经典Java面试题汇总

Volatile的特征: A、禁止指令重排(有例外) B、可见性 Volatile的内存语义: 当写一个volatile变量时,JMM会把线程对应的本地内存中的共享变量值刷新到主内存。 当读一个volatile变量时,J...

Java团长17
07/11
0
0
阿里、京东、美团、百度面试总结

一 、美团共三面,三面结束后hr会在当天或者一周内和你联系谈薪资。谈薪资是需要银行流水的。 一面: 1、ConcurrentHashMap实现原理 2、HashMap实现原理 3、锁的实现原理 4、synchronized和重...

会飞的蝌蚪
2017/11/27
0
0
Android Serializable与Parcelable原理与区别

一、序列化、反序列化是什么? (1) 名词解释 对象的序列化 : 把Java对象转换为字节序列并存储至一个储存媒介的过程。 对象的反序列化:把字节序列恢复为Java对象的过程。 (2) 序列化详细解释 ...

KingMing
2015/04/16
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

数据结构与算法2

一个数组的例子,实现查找,显示和删除的功能。 public class array {public static void main(String[] args){long[] arr;arr = new long[100];int nElems = 0;int j;...

沉迷于编程的小菜菜
9分钟前
0
0
Python3 基于 requests 批量下载图片

Python3 基于 requests 批量下载图片 import requestsheaders = {'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8','Accept-Encod......

leeyi
10分钟前
0
0
Sparkstreaming and Kafka

简介 Kafka 0.10的Spark Streaming集成设计与0.8 Direct Stream方法类似。 它提供了简单的并行性,Kafka分区和Spark分区之间的1:1对应关系,以及对偏移量和元数据的访问。 但是,由于较新的...

刺猬一号
14分钟前
0
0
java获取当前时间所在一周的周一和周日日期

/** * 当前时间所在一周的周一和周日时间 * @param time 当前时间 * @return */ public static Map getWeekDate(String time) { Map map = new HashedMap(); SimpleDateFormat sdf = new Si......

小弱鸡
42分钟前
0
0
Redis数据的导出和导入(dump和load方式)

网上有些文章已经不再适用,本人也是踩了些坑,在此记录下。 迁移redis数据一般有如下3种方式: 第三方工具redis-dump,redis-load aof机制,需要开启aof功能 rdb存储机制 这里介绍第一种方式...

iplusx
47分钟前
1
0
ElasticSearch 高亮显示大文档搜索结果

2016年12月,我们开始研究Ambar——一个文档搜索系统。Ambar使用ElasticSearch作为核心搜索引擎。 在Ambar开发的过程中,我们处理了很多与ES相关的问题,我们想分享我们得到的宝贵经验。让我...

九州暮云
今天
1
0
Python 使用 pywifi 模块 破解wifi密码

git https://github.com/awkman/pywifi 常见常量 from pywifi import const# Define interface status.IFACE_DISCONNECTED = 0IFACE_SCANNING = 1IFACE_INACTIVE = 2IFACE_CONNEC......

阿豪boy
今天
1
0
phpstorm使用Iedis

phpstorm的redis插件Iedis是真好用 看了网上挺多的文章,但是由于我系统还是ubuntu,就有点尴尬了,现在破解之后,留个笔记,即使自己之后有需要也可以很快翻阅 先下载资源 资源下载 zip压缩...

贤郎--均灵
今天
0
0
第三章 spring-bean之FactoryBeanRegistrySupport(4)

前言 从FactoryBeanRegistrySupport类的名字可以看出FactoryBeanRegistrySupport负责FactoryBean的注册与支持。如果想知道FactoryBean相关的资料,请阅读spring-bean中关于FactoryBean的解读...

鸟菜啊
今天
0
0
CentOS “Destination Host Unreachable”问题解决办法

挑战极速安装CentOS时遇到局域网主机不能通信的情况: [root@zjd network-scripts]# ping 8.8.8.8PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data.64 bytes from 8.8.8.8: icmp_seq=1 ttl=......

wffger
今天
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部