多线程编程核心技术(三)Java内存模型
2021-03-08 23:31
标签:get 释放 htm 直接 lan 就是 简单 app als 如果说造成线程不安全的情况是来源有时序性(代码优化),可见性(缓存一致性),原子性(线程切换)。 那么最简单的优化方式就是禁用缓存和编译优化。这样可以直接解决问题,就是代码的性能会相对的下降。合理的方案应该是按需禁用缓存以及编译优化。 这样的话就可以分治不同的代码,有并发的代码进行调整,没有并发的代码则可以继续之前的。 Java模型中规范的三个解决这类问题的关键字是 volatile,synchronized和final,以及Happens-Before规则。 volatile在C语言里面也有,本质是禁用高速缓存(强制刷新)。 这个代码在Java1.5之前可能为0,问题在于x可能被缓存了,导致另外一个线程虽然看到了v=true,但是x依然是0; 在java1.5成功解决了这个问题,Happens-Before规则的含义就是前面的操作对后面的操作是可见的,也就是做线程A进行了读写操作,那么B肯定能看到A读写之后的最新的变量的值。 Happens-Before的6大规则就是: 1.程序的顺序性规则:程序前面对某个变量的修改对后续的程序是可见的,例如volatile修改了v,v对后面的线程二是可见的 2.volatile变量规则:在新的内存模型中,volatile周围的普通字段不能随便重排;编译器生成字节码时,会在volatile写操作的前面和后面分别插入内存屏障(StoreStore屏障|volatile写|StoreLoad屏障),其中StoreStore屏障:禁止上面的普通写和下面的volatile写重排序;StoreLoad屏障:防止上面的volatile写与下面可能有的volatile读/写重排序。 3.传递性:这条规则是指如果 A Happens-Before B,且 B Happens-Before C,那么 A Happens-Before C。 花里胡哨的,其实就是如果你用了volatile,volatile会导致x的可见性需要保障,那么后面线程读的时候(线程读的时候需要对volatile进行判断),就会从主存中进行读取。边界就是只要给volatile赋值成功,那么这个赋值语句之前所有代码的执行结果都对其他线程可见 所以应该是将有volitile执行结果的cpu全部缓存强制刷新到内存,然后强制将其它cpu中的全部缓存和内存同步。 4.管程中锁的规则:管程(monitor)只是保证了同一时刻只有一个进程在管程内活动,即管程内定义的操作在同一时刻只被一个进程调用(由编译器实现). 管程(monitor)只是保证了同一时刻只有一个进程在管程内活动,即管程内定义的操作在同一时刻只被一个进程调用(由编译器实现).管程中的锁在 Java 里是隐式实现的,例如下面的代码,在进入同步块之前,会自动加锁,而在代码块执行完会自动释放锁,加锁以及释放锁都是编译器帮我们实现的。 5. 线程 start() 规则:指主线程 A 启动子线程 B 后,子线程 B 能够看到主线程在启动子线程 B 前的操作。 多线程编程核心技术(三)Java内存模型 标签:get 释放 htm 直接 lan 就是 简单 app als 原文地址:https://www.cnblogs.com/SmartCat994/p/14188022.htmlclass VolatileExample {
int x = 0;
volatile boolean v = false;
public void writer() {
x = 42;
v = true;
}
public void reader() {
if (v == true) {
// 这里x会是多少呢?
}
}
}
上一篇:tomcat JAVA_OPTS
下一篇:js 单例模式
文章标题:多线程编程核心技术(三)Java内存模型
文章链接:http://soscw.com/index.php/essay/62038.html