Java内存模型解决了并发程序中的 可见性问题 和 有序性问题
volatile 、 synchronized 和 final 关键字,以及六个 Happens-Before 规则 volatile int x = 0 :告诉编译器,对这个变量的读写,不能使用CPU缓存, 必须从内存中读取或者写入 public class VolatileExample {
private int x = 0;
private volatile boolean v = false;
// 线程A
public void writer() {
x = 42;
v = true;
}
// 线程B
public void reader() {
if (v) {
// 这里 x 会是多少呢?
}
}
}
v=true 写入内存 v==true
在 同一个线程 中,按照程序顺序,前面的操作Happens-Before于后面的任意操作
x=42 Happens-Before v=true v=true Happens-Before读变量 v=true x=42 Happens-Before读变量 v=true
v=true ,那么线程A设置的 x=42 对线程B是可见的,即线程B能看到 x==42 public void fun() {
synchronized (this) { // 此处自动加锁
// x 是共享变量, 初始值 =10
if (this.x < 12) {
this.x = 12;
}
} // 此处自动解锁
}
synchronized 就是Java对 管程的实现 Thread B = new Thread(() -> {
// 主线程调用 B.start() 之前
// 所有对共享变量的修改,此处皆可见
// 此例中,var==77
System.out.println(var);
});
// 此处对共享变量 var 修改
var = 77;
// 主线程启动子线程
B.start();
Thread B = new Thread(() -> {
// 此处对共享变量 var 修改
System.out.println(var); // 77
var = 66;
});
// 例如此处对共享变量修改,
// 则这个修改结果对线程 B 可见
// 主线程启动子线程
var = 77;
B.start();
B.join();
// 子线程所有对共享变量的修改
// 在主线程调用 B.join() 之后皆可见
// 此例中,var==66
System.out.println(var); // 66
public class EscapeExample {
public static Object global_obj;
final int x;
final int y;
// 错误的构造函数,尽量避免
public EscapeExample() {
x = 3;
y = 4;
// 此处就是将 this 逸出
// 其他线程通过global_obj读取的x可能是0,不满足x被修饰为final的语义
global_obj = this;
}
}
转载请注明出处:http://zhongmingmao.me/2019/04/15/java-concurrent-memory-model/
访问原文「 Java并发 -- Java内存模型 」获取最佳阅读体验并参与讨论