多线程可能对应着多个 CPU,多个 CPU 对应着多套缓存(L1, L2, L3, 寄存器)。缓存的数据可能和内存的不一致。 volatile 是为了解决不一致(同步)的问题。在读一个 volatile 变量的时候会直接去内存读,写时会马上更新到内存。
The Java volatile Happens-Before Guarantee[1]
When a thread writes to a volatile variable, then not just the volatile variable itself is written to main memory. Also all other variables changed by the thread before writing to the volatile variable are also flushed to main memory. When a thread reads a volatile variable it will also read all other variables from main memory which were flushed to main memory together with the volatile variable.
Java 5 之后增加了这个规则,这样就不需要把每个需要可见的变量声明为 volatile,只需要在 volatile 的变量更新前更新即可。
对性能的影响
Reading and writing of volatile variables causes the variable to be read or written to main memory. Reading from and writing to main memory is more expensive than accessing the CPU cache. Accessing volatile variables also prevent instruction reordering which is a normal performance enhancement technique. Thus, you should only use volatile variables when you really need to enforce visibility of variables.
与锁和 synchronized 的区别和联系
锁和 synchronized 是为了保证关键区的原子性,隐含了可见性(即在关键区内读应该也是从内存读,离开关键区会把更新刷新到内存)来保证同步。
网友评论