java并发编程实战《二十一》无锁工具类
2024-10-18 18:28:55
不安全的累加代码,如下
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的实现
太特么打击人了,想编译成功太耗费时间,先抛了。
最新文章
- 深入理解CSS盒子模型
- js正则表达式图形化工具-rline
- ZC706以太网扩展板接口
- (十) 一起学 Unix 环境高级编程 (APUE) 之 线程控制
- Json(2)-DataContractJsonSerializer
- EIGamal密码体制
- MongoDB的安装和基本操作
- 关于安装linux时要怎么分区的考虑的參考方式?
- MySQL数据库安装(CentOS操作系统/tar.gz方式)
- 微信小程序 服务器端生成用户登陆环节的 3rd_session
- 【20171027中】alert(1) to win 第13,14,15,16题
- Wannafly挑战赛3 record
- pd.read_csv() 、to_csv() 之 常用参数
- Hibernate若干知识点
- Python中多个列表与字典的合并方法
- 【Android】让Python在Android系统上飞一会儿
- Java面试(一) -- 基础部分(1)
- 【转载】COM 组件设计与应用(六)——用 ATL 写第一个组件
- 铁轨(rails, ACM/ICPC CERC 1997,Uva 514)
- Asp.net MVC Comet 推送