java并发编程实战《二十一》无锁工具类
不安全的累加代码,如下
1 public class Test {
2 long count = 0;
3 void add10K() {
4 int idx = 0;
5 while(idx++ < 10000) {
6 count += 1;
7 }
8 }
9 }
不安全的原因是count的可见性以及count += 1的原子性
使用AtomicLong
1 public class Test {
2 AtomicLong count =
3 new AtomicLong(0);
4 void add10K() {
5 int idx = 0;
6 while(idx++ < 10000) {
7 count.getAndIncrement();
8 }
9 }
10 }
好处:
性能提升
原理:
硬件支持。CPU 为了解决并发问题,提供了 CAS 指令(CAS,全称是 Compare And Swap,即“比较并交换”)。
CAS 指令包含 3 个参数:共享变量的内存地址 A、用于比较的值 B 和共享变量的新值 C;并且只有当内存中地址 A 处的值等于 B 时,才能将内存中地址 A 处的值更新为新值 C。作为一条 CPU 指令,CAS 指令本身是能够保证原子性的。
源码:
1 final long getAndIncrement() {
2 return unsafe.getAndAddLong(
3 this, valueOffset, 1L);
4 }
思考:这里为什么要传this?来看一下AtomicLong这个类的结构

重点看成员变量,getAndAddLong传this和offset肯定是为了获取这个value值,但是为什么不直接传value?实际上这就是引用传值和非引用传值,value是成员变量,从共享内存读,如果直接非引用传值,那在value传入后加入内存屏障之前共享内存中value的值被修改了怎么办?
源码:
1 public final long getAndAddLong(
2 Object o, long offset, long delta){
3 long v;
4 do {
5 // 读取内存中的值
6 v = getLongVolatile(o, offset);
7 } while (!compareAndSwapLong(
8 o, offset, v, v + delta));
9 return v;
10 }
11 //原子性地将变量更新为x
12 //条件是内存中的值等于expected
13 //更新成功则返回true
14 native boolean compareAndSwapLong(
15 Object o, long offset,
16 long expected,
17 long x);
总结:
原子类针对单个共享变量,多个共享变量使用互斥锁
以上,还没说完,
另外还有CAS的ABA问题
等等搞一下openjdk的源码编译,看看compareAndSwapLong的实现
太特么打击人了,想编译成功太耗费时间,先抛了。
java并发编程实战《二十一》无锁工具类的更多相关文章
- Java并发编程实战.笔记十一(非阻塞同步机制)
关于非阻塞算法CAS. 比较并交换CAS:CAS包含了3个操作数---需要读写的内存位置V,进行比较的值A和拟写入的新值B.当且仅当V的值等于A时,CAS才会通过原子的方式用新值B来更新V的值,否则不 ...
- 【Java并发编程】2、无锁编程:lock-free原理;CAS;ABA问题
转自:http://blog.csdn.net/kangroger/article/details/47867269 定义 无锁编程是指在不使用锁的情况下,在多线程环境下实现多变量的同步.即在没有线程 ...
- 【JAVA并发编程实战】8、锁顺序死锁
package cn.study.concurrency.ch10; public class Account { private String staffAccount; //账号 private ...
- java并发编程(二十一)----(JUC集合)CopyOnWriteArraySet和ConcurrentSkipListSet介绍
这一节我们来接着介绍JUC集合:CopyOnWriteArraySet和ConcurrentSkipListSet.从名字上来看我们知道CopyOnWriteArraySet与上一节讲到的CopyOn ...
- 【JAVA并发编程实战】9、锁分段
package cn.study.concurrency.ch11; /** * 锁分段 * @author xiaof * */ public class StripedMap { //同步策略:就 ...
- Java并发编程阅读笔记-同步容器、工具类整理
- java并发编程实战《二》java内存模型
Java解决可见性和有序性问题:Java内存模型 什么是 Java 内存模型? Java 内存模型是个很复杂的规范,可以从不同的视角来解读,站在我们这些程序员的视角,本质上可以理解为, Java 内存 ...
- 【Java并发编程实战】----- AQS(二):获取锁、释放锁
上篇博客稍微介绍了一下AQS,下面我们来关注下AQS的所获取和锁释放. AQS锁获取 AQS包含如下几个方法: acquire(int arg):以独占模式获取对象,忽略中断. acquireInte ...
- Java并发编程实战 03互斥锁 解决原子性问题
文章系列 Java并发编程实战 01并发编程的Bug源头 Java并发编程实战 02Java如何解决可见性和有序性问题 摘要 在上一篇文章02Java如何解决可见性和有序性问题当中,我们解决了可见性和 ...
- 【Java并发编程实战】-----“J.U.C”:ReentrantLock之一简介
注:由于要介绍ReentrantLock的东西太多了,免得各位客官看累,所以分三篇博客来阐述.本篇博客介绍ReentrantLock基本内容,后两篇博客从源码级别分别阐述ReentrantLock的l ...
随机推荐
- Centos 7挂载本地ISO光盘
在Linux系统上挂载系统镜像作为yum本地仓库或者安装某个常用RPM包. mount语法: mount -t 类型 -o 挂接方式 源路径 目标路径 -t 选项: iso9660:光盘或光盘镜像 m ...
- Pandas_分组与聚合
# 分组统计是数据分析中的重要环节: # 1-数据分组:GroupBy的原理和使用方法: # 2-聚合运算:学会分组数据的聚合运算方法和函数使用: 类似于 SQL思想 # 3-分组运算:重点 appl ...
- 强迫自己学Jquery
Jquery 适合我吗? 里面有很多用不上的功能, 我需要什么,常用的判断,常用的扩展,来自Dojo的Hitch函数,事件绑定,样式处理(添加 删除 替换),Ajax,模块加载, 足够了,真心不想用这 ...
- JAVA基础之接口与内部类
接口与内部类 目录 接口与内部类 1. Lambda表达式 1. 关于懒计算 2. Predicate接口 3. 关于方法引用 4. 关于构造器引用 5. 关于变量的作用域 2. 内部类 1. 局部内 ...
- MySql Binlog 说明 & Canal 集成MySql的更新异常说明 & MySql Binlog 常用命令汇总
文章来源于本人的印象笔记,如出现格式问题可访问该链接查看原文 原创声明:作者:Arnold.zhao 博客园地址:https://www.cnblogs.com/zh94 目录 背景介绍 开启MySq ...
- Ceph如何实现文件系统的横向扩展
前言 在跟一个朋友聊天的时候,聊到一个技术问题,他们的一个环境上面小文件巨多,是我目前知道的集群里面规模算非常大的了,但是目前有个问题,一方面会进行一倍的硬件的扩容,而文件的数量也在剧烈的增长着,所以 ...
- Git 分支相关
创建分支 git branch dev 切换分支 git checkout dev (dev换成-可切换为上一个使用的分支) 以上两个可合并为 git checkout -b dev 将新分支推送到远 ...
- 一个工作三年左右的Java程序员和大家谈谈从业心得
转发链接地址:https://mp.weixin.qq.com/s/SSh9HcA5PgMHv7xiolQkig 貌似这一点适应的行业最广,但是我可以很肯定的说:当你从事web开发一年后,重新找工作时 ...
- 对于线程池ThreadPool的学习总结
线程池:就是一个管理线程的池子. 优点: 它帮我们管理线程,避免增加创建线程和销毁线程的资源损耗.因为线程其实也是一个对象,创建一个对象,需要经过类加载过程,销毁一个对象,需要走GC垃圾回收流程,都是 ...
- 在FL Studio编曲软件中查找采样的音高
相信玩音乐的小伙伴们都遇到过这种情况,在用FL Studio编曲时,想添加一段音频采样,由于采样的调式与我们正在编曲的调式不同,音频之间的衔接就是一个非常头疼的问题,要解决采样的调式,我们就得先确认这 ...