Volatile 关键字

2018-05-25  本文已影响0人  tdwmarlboro

Volatile修饰的成员变量在每次被线程访问时,都强迫从共享内存中重读该成员变量的值。而且,当成员变量发生变化时,强迫线程将变化值回写到共享内存。这样在任何时刻,两个不同的线程总是看到某个成员变量的同一个值。

volatile 不保证原子操作,所以,很容易读到脏数据。

volatile 的使用场景:

通过关键字synchronized 可以防止多个线程进入同一段代码,在某些特定场景中,volatile相当于一个轻量级的synchronized,因此不会引起线程的上下文切换,但是使用volatile必须满足两个条件:

1、对变量的写操作不依赖当前值,如多线程下执行a++,是无法通过volatile 保证结果准确性的;

2、该变量没有包含在具有其它变量的不变式中

使用建议:在两个或者更多的线程访问的成员变量上使用volatile。当要访问的变量已在synchronized 代码块中,或者为常量时,不必使用。

可见性:当一个共享变量被volatile修饰时,它会保证修改的值立即被更新到主存,所以对其他线程是可见的。当其他线程需要读取该值时,其他线程会去主存中读取新值。

有序性:java内存模型中允许编译器和处理器对指令进行重排序,虽然重排序过程不会影响到单线程执行的正确性,但是会影响到多线程并发执行的正确性。这时可以通过volatile来保证有序性,除了volatile,也可以通过synchronized和Lock来保证有序性。synchronized和Lock保证每个时刻只有一个线程执行同步代码,这相当于让线程顺序执行同步代码,从而保证了有序性。如果不考虑原子性操作的话volatile比synchronized和Lock更轻量级,成本更低。

不保障原子性: volatile关键字只能保证共享变量的可见性和有序性。如果volatile修饰并发线程中共享变量, 而该共享变量是非原子操作的话,并发中就会出现问题。

上一篇下一篇

猜你喜欢

热点阅读