Java并发编程实战~原子类

对于简单的原子性问题,还有一种无锁方案,先看看如何利用原子类解决累加器问题。

public class Test {AtomicLong count = new AtomicLong(0);public void add10K() {int idx = 0;while(idx++ < 10000) {count.getAndIncrement();}}}

无锁方案相对互斥锁方案,最大的好处就是性能。

无锁方案的实现原理

其实原子类性能高的秘密很简单,硬件支持而已。CPU 为了解决并发问题,提供了 CAS 指令(CAS,全称是 Compare And Swap,即“比较并交换”)。CAS 指令包含 3 个参数:共享变量的内存地址 A、用于比较的值 B 和共享变量的新值 C;并且只有当内存中地址 A 处的值等于 B 时,才能将内存中地址 A 处的值更新为新值 C。作为一条 CPU 指令,CAS 指令本身是能够保证原子性的。

你可以通过下面 CAS 指令的模拟代码来理解 CAS 的工作原理。在下面的模拟程序中有两个参数,一个是期望值 expect,另一个是需要写入的新值 newValue,只有当目前 count的值和期望值 expect 相等时,才会将 count 更新为 newValue

class SimulatedCAS{int count;public synchronized int cas(int expect, int newValue){// 读目前 count 的值int curValue = count;// 比较目前 count 值是否 == 期望值if(curValue == expect){// 如果是,则更新 count 的值count = newValue;}// 返回写入前的值return curValue;}}

使用 CAS 来解决并发问题,一般都会伴随着自旋,而所谓自旋,其实就是循环尝试。

class SimulatedCAS{volatile int count;// 实现 count+=1public void addOne(){do {newValue = count+1; //①}while(count != cas(count,newValue) //②}// 模拟实现 CAS,仅用来帮助理解public synchronized int cas(int expect, int newValue){// 读目前 count 的值int curValue = count;// 比较目前 count 值是否 == 期望值if(curValue == expect){// 如果是,则更新 count 的值count= newValue;}// 返回写入前的值return curValue;}
}

但是在 CAS 方案中,有一个问题可能会常被你忽略,那就是ABA的问题。什么是 ABA 问题呢?

假设 count 原本是 A,线程 T1 在执行完代码①处之后,执行代码②处之前,有可能 count 被线程 T2 更新成了 B,之后又被 T3 更新回了 A,这样线程T1 虽然看到的一直是 A,但是其实已经被其他线程更新过了,这就是 ABA 问题。

Java 如何实现原子化的 count += 1

在 Java 1.8 版本中,getAndIncrement() 方法会转调 unsafe.getAndAddLong() 方法。这里 this 和 valueOffset 两个参数可以唯一确定共享变量的内存地址。

final long getAndIncrement() {return unsafe.getAndAddLong(this, valueOffset, 1L);
}

unsafe.getAndAddLong() 方法的源码如下

public final long getAndAddLong(Object o, long offset, long delta){long v;do {// 读取内存中的值v = getLongVolatile(o, offset);} while (!compareAndSwapLong(o, offset, v, v + delta));return v;
}// 原子性地将变量更新为 x
// 条件是内存中的值等于 expected
// 更新成功则返回 true
native boolean compareAndSwapLong(Object o, long offset, long expected,long x);

原子类概览

 1. 原子化的基本数据类型

getAndIncrement() // 原子化 i++
getAndDecrement() // 原子化的 i--
incrementAndGet() // 原子化的 ++i
decrementAndGet() // 原子化的 --i
// 当前值 +=delta,返回 += 前的值
getAndAdd(delta) 
// 当前值 +=delta,返回 += 后的值
addAndGet(delta)
//CAS 操作,返回是否成功
compareAndSet(expect, update)
// 以下四个方法
// 新值可以通过传入 func 函数来计算
getAndUpdate(func)
updateAndGet(func)
getAndAccumulate(x,func)
accumulateAndGet(x,func)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/496724.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

著名物理学家斯蒂芬•霍金去世,他曾告诫人类要学会避免人工智能可能的风险

据多家媒体报道&#xff0c;著名的英国物理学家斯蒂芬霍金于3 月 14 日去世&#xff0c;享年 76 岁。霍金教授的孩子露西&#xff0c;罗伯特和蒂姆发表了声明确认了这一消息。斯蒂芬威廉霍金(Stephen William Hawking)&#xff0c;1942年1月8日出生于英国牛津&#xff0c;英国剑…

对《生产流水线模式》讨论的总结性回复

我的上一篇文章《生产流水线模式》发布以后&#xff0c;引起了很多朋友的关注&#xff0c;大家发表了很多意见&#xff0c;现在我针对留言中大家提得比较多的问题&#xff0c;做一个总结性的回复。 问题一&#xff1a;我的敏捷开发架构是不是只实现了简单的增删改查功能&#x…

C++学习之路 | PTA乙级—— 1091 N-自守数 (15 分)(精简)

1091 N-自守数 (15 分) 如果某个数 K 的平方乘以 N 以后&#xff0c;结果的末尾几位数等于 K&#xff0c;那么就称这个数为“N-自守数”。例如 392​2​​25392&#xff0c;而 25392 的末尾两位正好是 92&#xff0c;所以 92 是一个 3-自守数。 本题就请你编写程序判断一个给定…

电路板上的插头怎么拔下来_空调插头一直不拔费电吗?实测一周竟然发现了真相!...

随着气温的不断走低&#xff0c;全国绝大部分城市已经进入了真正意义上的秋天。那么&#xff0c;经过了酷热一夏&#xff0c;你家的空调电源插头拔掉了吗? 说道空调&#xff0c;想必大家都知道这“家伙”可是耗电大户。尤其在七八月份&#xff0c;几乎都是24小时不停机在运行。…

C++ stringstream

参考&#xff1a;http://www.usidcbbs.com/read-htm-tid-1898.html 常见格式串 %% 印出百分比符号&#xff0c;不转换。 %c 整数转成对应的 ASCII 字元。 %d 整数转成十进位。 %f 倍精确度数字转成浮点数。 %o 整数转成八进位。 %s 整数转成字符串。 %x 整数转成小写十六进位…

Java并发编程实战~思维导图

#原图 System.out.println("https://www.processon.com/view/link/61a235be1efad425fd6ff5f6")

中国“脑计划”研究正在悄然布局

来源&#xff1a;中国科学报 作者&#xff1a;黄辛 作为“十三五”上海科研发展的重点&#xff0c;一张神奇的脑计划研究“地图”正在悄然加紧布局。日前&#xff0c;在教育部科技司、国家自然科学基金委员会政策局、华东师范大学主办的“交叉融合的教育科学基础研究”研讨会上…

C++学习之路 | PTA乙级——1092 最好吃的月饼 (20 分)(精简)

1092 最好吃的月饼 (20 分)、 月饼是久负盛名的中国传统糕点之一&#xff0c;自唐朝以来&#xff0c;已经发展出几百品种。 若想评比出一种“最好吃”的月饼&#xff0c;那势必在吃货界引发一场腥风血雨…… 在这里我们用数字说话&#xff0c;给出全国各地各种月饼的销量&…

JDBC链接SQLServer2005 Express

SQLServer2005的数据库链接的jar包可以到微软网站上去下载&#xff0c;驱动和链接字符串如下&#xff1a; 1: String driver "com.microsoft.sqlserver.jdbc.SQLServerDriver"; 2: String url "jdbc:sqlserver://localhost:1433;databaseNamepubs"; SQLS…

dnf时装预览怎么打开_DNF:史上最好看时装上线,大佬已经玩疯,全服都是真香的气息...

大家好&#xff01;我是风柜君&#xff0c;这次又是我来给大家带来DNF游戏内外的趣事&#xff0c;希望各位喜欢。DNF国服将在6月18日迎来第11周年庆&#xff0c;而在此之前&#xff0c;国服在6月6日的时候已经更新了一波周年庆预热活动。这次的更新除了普雷妮普通副本以外&…

Java并发编程实战~Immutability模式

解决并发问题&#xff0c;其实最简单的办法就是让共享变量只有读操作&#xff0c;而没有写操作。这个办法如此重要&#xff0c;以至于被上升到了一种解决并发问题的设计模式&#xff1a;不变性&#xff08;Immutability&#xff09;模式。所谓不变性&#xff0c;简单来讲&#…

深度解析:AWS、谷歌云、IBM Cloud和微软 Azure四巨头2018将会有哪些布局?

来源&#xff1a; IDC圈近来&#xff0c;公司规模已经不再是企业选择云服务商的重要因素&#xff0c;市场对云服务商优劣的判断有了多种标准。企业对全球一些大型云计算服务商&#xff08;例如亚马逊AWS&#xff0c;谷歌云平台&#xff0c;IBM Cloud和微软 Azure等&#xff09;…

讲解SQL Server定时作业job的设置方法

如果在SQL Server 里需要定时或者每隔一段时间执行某个存储过程或3200字符以内的SQL语句时,可以用管理->SQL Server代理->作业来实现。 ◆1、管理->SQL Server代理->作业(按鼠标右键)->新建作业-> ◆2、新建作业属性(常规)->名称[自定义本次作业的名称]…

C++学习之路 | PTA乙级—— 1093 字符串A+B (20 分)(精简)

1093 字符串AB (20 分) 给定两个字符串 A 和 B&#xff0c;本题要求你输出 AB&#xff0c;即两个字符串的并集。要求先输出 A&#xff0c;再输出 B&#xff0c;但重复的字符必须被剔除。 输入格式&#xff1a; 输入在两行中分别给出 A 和 B&#xff0c;均为长度不超过 10​6​​…

用法 stl_C++STL 容器篇

前言上一章节主要是详细介绍了C泛型编程基础&#xff0c;不清楚的可以回顾一下哦。本章节主要针对于CSTL(标准模板类库)做个详细介绍。标准模板类库也就是别人写的模板类&#xff0c;主要内容是各种数据结构的封装&#xff0c;以及常用算法。暂时分三个章节介绍&#xff0c;本章…

超级强大的 vim 配置(vimplus)

From : http://www.cnblogs.com/highway-9/p/5984285.html From : http://www.cnblogs.com/ma6174/archive/2011/12/10/2283393.html From : http://www.cnblogs.com/youxia/p/linux002.html From : http://blog.csdn.net/namecyf/article/details/7787479 最近在重新配置Vim&a…

谷歌将屏蔽一切与加密货币相关的广告 6月正式生效

来源&#xff1a;腾讯证券北京时间3月14日下午消息&#xff0c;据外媒报道&#xff0c;谷歌开始对与加密货币相关的广告的进行打击。谷歌可持续广告业务负责人斯科特-斯宾塞&#xff08;Scott Spencer&#xff09;在接受CNBC采访时称&#xff0c;该公司正在调整与金融服务相关的…

Java并发编程实战~Copy-on-Write模式

Copy-on-Write 模式的应用领域 1、在操作系统领域。类 Unix 的操作系统中创建进程的 API 是 fork()&#xff0c;传统的 fork() 函数会创建父进程的一个完整副本 2、很多文件系统也同样用到了&#xff0c;例如 Btrfs (B-Tree File System)、aufs&#xff08;advanced multi-la…

[导入]身份验证方面的问题

目前再研究Discuz !NT 1.0源码发现它Web.config中设置,为什么不用Form方式,有谁能说说?文章来源:http://topic.csdn.net/u/20080828/11/051abbea-ba95-466d-afcd-82bbb0f647e3.html转载于:https://www.cnblogs.com/zengxlf/articles/1279232.html

ARM体系结构与汇编指令

可编程器件的特点 • CPU在固定频率的时钟控制下节奏运行。 • CPU可以通过总线读取外部存储设备中的二进制指令集&#xff0c;然后解码执行。 • 这些可以被CPU解码执行的二进制指令集是CPU设计的时候确定的&#xff0c;是CPU的设计者&#xff08;ARM公司&#xff09;定义的&a…