Java并发编程——为什么要用volatile关键字 (2)

现在考虑重排序后,两个线程发生了以下调用:

Time Thread A Thread B
T1   检查到uniqueSingleton为空    
T2   获取锁    
T3   再次检查到uniqueSingleton为空    
T4   为uniqueSingleton分配内存空间    
T5   将uniqueSingleton指向内存空间    
T6     检查到uniqueSingleton不为空  
T7     访问uniqueSingleton(此时对象还未完成初始化)  
T8   初始化uniqueSingleton    

在这里添加volatile关键字主要是避免在对象未完整完成对象创建就已经被其他线程读取,造成空指针异常。

总结

volatile 的主要作用是实现可见性和禁止指令重排。

线程安全需要满足可见性、有序性、原子性。

volatile 可以保证可见性和有序性,但是无法保证原子性,所以是线程不安全的。(非原子操作可能会导致数据缓存在CPU的cache中,产生数据不一致)

synchronized 关键字虽然可以保证可见性、有序性、原子性,而且用法简单,但是性能开销大。

双重检查锁模式是 volatile 的典型使用场景,双重检查锁通常用于实现单例模式或延迟赋值。

参考

Java中Volatile关键字详解

java volatile关键字解惑

为什么双重检查锁模式需要 volatile ?

Java中的双重检查锁(double checked locking)

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zzddzj.html