首页 💎并发编程_volatile
文章
取消

💎并发编程_volatile

volatile

1.可见性

原理:X86处理器下:带volatie的变量 翻译成汇编码是:lock addl.. 意思是在寄存器上进行一个空操作 ​ 实现可见性的关键是lock前缀!在多核处理器下lock前缀会做两件事 ​ 1.把更新的值推送到主存 ​ lock信号保证在处理期间 锁定这块内存的缓存行 并且写回主存 然后使用缓存一致性协议来保证修改的 原子性 缓存一致性协议会阻止同时修改两个以上的缓存行 ​ 2.致其他缓存了该变量的缓存行无效 ​ 在缓存一致性协议的下 其他处理器会通过cpu的嗅探技术 查看自己的内存的缓存行的数据是否被修改 ​ 如果是则致缓存行无效

2.有序性(防止重排序)

​ ·为什么出现指令重排序?-为了提高性能 ​ ·重排的分类: ​ 1.编译器:在不改变单线程程序语义情况下 可以重排序 ​ 对于编译器重排JMM的编译器重排规则会禁止某些重排序 ​ 2.处理器:数据间不存在依赖性则可以重排序 ​ 对于处理器重排 通过加入内存屏障来实现重排序 ​ 内存屏障: ​ Store Store Barriers:写-写不能重排序 ​ Store Load Barriers:写-读不能重排序 ​ Load Load Barriers:读-读不能重排序 ​ Load Store Barriers:读-写不能重排序

​ ·happens-before规则 ​ ·线程内的所以操作都happens-before后续操作 ​ ·锁的释放happens-before 随后对这个对象的加锁 ​ ·volatile变量的写 happens-before 在volatile 的读 ​ ·A happens-before B — B happens-before C –> A happens-before C ​ ·as-if-serial原则: ​ 不管怎么重排都不会对有数据依赖的操作重新排序

​ happens-before和as-if-serial本质是一回事 ​ as-if-serial:保证单线程内程序的结果不变 happens-before:保证正确的同步的多线程程序执行结果不变 ​ as-if-serial:单线程下程序看似是顺序执行的 happens-before:正确同步的多线程下程序看似是顺序执行的

​ volatile写:加Store Store Barriers 和Store Load Barriers:写-读不能重排序 ​ volatile读:加Load Load Barriers 和Load Store Barriers:写-读不能重排序

​ 应用:单例模式下的DCL为什么用volatile关键字? ​ 原因: ​ 1.创建对象分三步: ​ 开辟内存空间 赋默认值 ​ 调用构造 函数赋初始值 ​ 栈中的变量的引用指向堆中的地址 ​ 2.其中第二步和第三步在多线程的情况下 可能重排序 导致得到一个未初始化完全的对象 ​ 3.加了volatile关键字 会在 new instance 前加 Store Store屏障 在 其后加Store Load屏障 ​ 保证volatile写 完后才能读

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
//DCL单例
public class sigeton{
    private static volatile sigeton sgt;
    private sigeton(){};
    public sigeton getInstance(){
    	if(sgt==null){
           synchronized(this){
               if(sgt==null){
            		sgt = new sigeton();
        	}
           } 
        }
        return sgt;
    }
    
}								

3.原子性:

​ 只能保证单一变量的原子性

本文由作者按照 CC BY 4.0 进行授权

💎并发编程_synchronized

💎字节跳动夏令营项目 Tiktok