java并发艺术 散装笔记
2021-03-23 本文已影响0人
圆企鹅i
《JAVA并发编程的艺术》 方腾飞,魏鹏,程晓明 -- 笔记
1.避开死锁
1.1 避免一个线程获取多个锁
1.1 避免一个锁在锁内同时占用多个资源
1.1 尝试使用定时锁
1.1 对于数据库锁,加锁和解锁在一个数据库链接里。
2.资源限制
2.1网络限制
带宽固定
2.2线程限制
2.3资源竞争限制
3.底层实现
3.1 volatile
volatile 修饰变量 让所有线程看到的变量是一致的
3.1.1 模型
image.png会发现每个CPU(每条线程)都是在拿自己的数据在玩
所以在并发的情况下,有可能所有cpu都把原数据10进行+1,然后内存中数据被写了三次11
这说明,在某些场景,轻量级的volatile 比synchronize更加简单的高效
3.1.2 实现指令
-
LOCK指令
A .该汇编指令,会锁住CPU的缓存(近年的cpu 之前是锁主线程)
如果该缓存里面有对应内存的数据--->LOCK#指令 会将缓存回写到内存中 同时启用缓存锁定,阻止其他缓存修改
B. 处理器的嗅探技术,正在写数据的CPU将会使用嗅探到其他CPU也有该内存数据的缓存,并使其缓存无效
注意:CPU不直接和内存进行交互,而是缓存到L1/2/3级CPU缓存当中
3.2 volatile的字节补充优化
Douglea
JDK1.7 JAVA并发包中的队列集合 Linkded-TransferQueue队列
使用追加字节来优化缓存行的问题
P6系列和奔腾系列CPU缓存行32字节,其余64字节
队列里的头尾节点,因为经常操作的原因,必然面临多次写操作
如果队列里的数据字节过少,volatile使用的缓存锁定功能必然锁定头尾两个数据。
多线程同时处理头尾数据,则变成另一个CPU无法去修改头尾中的另一个,理想的并行变成串行。
所以,Douglea在头尾的两个对象,进行字节补充,补充到64位,则不会互相锁住,达到并行。
不过这种方式在Java7中可能不生效,它还设计了更加智慧的追加字节的方式。