介绍
我们经常看到volatile(易变的)修饰的变量,这个volatile是jvm提供的一种轻量级的同步手段,但是对于它自身使用场景,优缺点经常都是从每个片面的点去理解的,没有形成体系,打算总结下形式记忆体系。
volatile的特性
- 可见性
就是保证变量对于所有线程都是可见的。对于volatile修饰的变量的读总能看到最后对该变量的写。 - 原子性
就是保证任意单个volatile变量的读写操作具有原子性(但是volatile++这种复合操作不具备原子性)。
public class VolatileTest {
public static volatile int i = 0;
public static void iinc() {
i++;
}
public static void main(String[] args) {
for (int t = 0 ; t < 30 ; t++) {
new Thread(new Runnable() {
public void run() {
for (int j = 0 ; j < 1000 ; j++) {
iinc();
}
}
}).start();
}
while (Thread.activeCount() > 1) {
Thread.yield();
}
System.out.println(i);
}
}
1.jpg
说明:应对这个情况我们想要原子性的int值可以采用AtomicInteger类来解决问题。
happens-before中的volatile
之前java内存模型讲到,java内存模型会使用重排序来优化程序,单线程的情况下,虽然数据有依赖性,但是在单线程中java内存模型会遵守as-if-serial语义来保证结果不会因为重排序改变。但是在多线程下就无法保证指令重排序了;但是volatile变量是禁止指令重排序优化的。happens-before性质定义了规则:对于volatile变量得写操作happens-before读操作。
volatile内存语义
当写一个volatile变量时,java内存模型会把该线程对应的本地内存中的共享变量值刷新到主内存;store+write操作。
当读一个volatile变量时,java内存模型会把该线程对应的本地内存设置为无效,然后线程从主内存读取共享变量;read+load操作。
网友评论