Java并发编程实践笔记(四)——chapter3(重排序优化,可见性)

1.重排序

编译器重排序。

CPU重排序。

重排序会造成程序运行的结果和我们预期的不同。

同步机制会解决这个问题,但是重排序是一种优化手段,同步机制会破坏这一种优化,会在一定程度上影响性能。

非原子的64位操作

对于非原子的64位操作来说,高32位和低32位的操作是分开的,不是原子的,所以在多线程情况下,读线程可能读到了修改前的低32位和修改后的32位。

long和double类型的读写都有这种问题。

2.锁,volatile与可见性

1.synchronized与可见性

synchronized锁是可以解决可见性的问题的。
如果对一个变量的get和set方法都加上synchronized,那么set赋的值get是可见的,即使是在多线程的情况下。

2.volatile与可见性

但是如果只是单纯为了实现可见性,那么对该变量加上volatile即可。
如果对于volatile变量只有一个线程写入的话,那么就是线程安全的了,而且其他线程的可见性也保证了。

3.volatile的使用场景

用于确保它们所引用的对象状态的可见性,或者用于标识重要的生命周期时间(比如初始化或关闭)的发生。

场景一:生命周期结束

比如在声明周期结束的时候,把一个对象引用置位null,同时要让其他线程直到该对象声明周期已经结束,需要加上volatile。

场景二:懒加载

再比如懒加载的时候,让其它线程直到该对象已经加载,不需要再重新创建加载,这个时候也需要使用volatile。

场景三:状态标记

比如一个boolean变量来标识何时退出一个循环,为了让线程立即知道,这个时候也需要使用volatile。
使用场景总结:标识完成,中断和状态等场景。

4.volatile vs 锁

volatile只保证可见性,不能保证原子性。比如volatile int i,无法保证i++的原子性。
锁两者都可以保证。

猜你喜欢

转载自blog.csdn.net/xxcupid/article/details/52914390