注明:
参考书作者:方腾飞 魏鹏 程晓明
参考书目:《Java 并发编程的艺术》
volatile关键字
在了解volatile关键字之前,先了解一些cpu的术语定义,来给volatile铺路
术语 | 英文单词 | 术语描述 |
---|---|---|
内存屏障 | memory barriers | 是一组处理器指令,用于实现内存操作的顺序限制 |
缓冲行 | cache line | CPU高速缓存中可以分配的最小存储单位。处理器填写缓存行时会加载整个缓存行 |
原子操作 | atomic operations | 不可中断的一个或一系列操作 |
缓存行填充 | cache line fill | 当处理器识别到从内存中读取操作数是可缓存的,处理器读取整个高速缓存行到适当的缓存(L1,L2,L3) |
缓存命中 | cache hit | 如果进行高速缓存行填充操作的内存位置仍然是下次处理器访问的地址时,处理器从缓存中读取操作数,而不是从内存中读取 |
写命中 | write hit | 当处理器将操作数写回到一个内存缓存的区域时,首先会检查这个缓存的内存地址是否在缓存行中,如果存在一个有效的缓存行,则处理器将这个操作数写回到缓存,而不是写回到内存中,这个操作被称为写命中。 |
写缺失 | write misses the cache | 一个有效的缓存行被写入到不存在的内存区域 |
volatile变量修饰的共享变量进行写操作的时候会引发两件事情:
- 将当前处理器缓存行的数据写回到系统内存中
- 写回内存的操作会使其他CPU里的缓存了该内存地址的数据无效(缓存一致性)
上面是根据自己的理解画的图,可能会有偏差,还望指正
对volatile的变量进行写操作,进行如下步骤:
1.处理器I将数据写到缓存中
2.由于volatile的第一条性质的原因,会将数据写回到内存中
3.由于缓存一致性协议存在,处理器II嗅探到总线上传播的数据来检查自己的缓存是否过期
4.如果过期,则将缓存行设置为无效状态。
5.当处理器II对这个数据进行修改操作时,会重新从系统内存中把数据读取到处理器缓存中。
volatile使用优化
JAVA7并发包中,在使用volatile变量时,用追加字节的方式来优化队列出队和入队的性能
原因是:对于很多CPU的高速缓存行都是64个字节,当长度不足64个字节时,就会将头节点和尾节点读到一个高速缓存行中,而处理器试图修改头节点时,会锁定整个缓存行,此时尾节点也会被锁定,导致其他处理器不能访问自己高速缓存的尾节点,严重影响队列的入队和出队效率。
使用追加到64个字节的方式填充满高速缓冲区的缓存行,避免头节点和尾节点加载到同一个缓存行中,使头节点和尾节点在修改时不会互相锁定。