石景山网站建设服务,万能网站网址下载,网站建设的一般流程排序为,error 403 网站拒绝显示目录
一、Happens-Before模型简介
二、组成Happens-Before模型的八种规则
2.1 程序顺序规则#xff08;as-if-serial语义#xff09;
2.2 传递性规则
2.3 volatile变量规则
2.4 监视器锁规则
2.5 start规则
2.6 Join规则 一、Happens-Before模型简介
除了显示引用vo…目录
一、Happens-Before模型简介
二、组成Happens-Before模型的八种规则
2.1 程序顺序规则as-if-serial语义
2.2 传递性规则
2.3 volatile变量规则
2.4 监视器锁规则
2.5 start规则
2.6 Join规则 一、Happens-Before模型简介
除了显示引用volatile关键字能够保证可见性以外在Java中还有很多的可见性保障的规则。
从JDK1.5开始引入了一个happens-before的概念来阐述多个线程操作共享变量的可见性问题。所以我们可以认为在JMM中如果一个操作执行的结果需要对另一个操作可见那么这两个操作必须要存在 happens-before关系。这两个操作可以是同一个线程也可以是不同的线程。
JMM可以通过happens-before关系向程序员提供跨线程的内存可见性即如果A线程的写操作a与B线程的读操作b之间存在happens-before关系尽管a操作和b操作不在同一个线程中执行但是JMM向程序员保证a操作对b操作可见。具体定义为
如果一个操作happens-before另外一个操作发生在另一个操作之前那么第一个操作的执行结果对第二个操作可见且第一个操作的执行顺序在第二个操作之前。两个操作之间存在happens-before关系并不意味着Java平台的具体实现必须要按照happens-before关系指定的顺序来执行。如果重排序之后的执行结果与按happens-before关系来执行的结果一致那么这种重排序并不非法也就是说JMM允许这种重排序。
上面两条规则第一条是JMM对程序员的保证。从程序员的角度可以这样理解happens-before如果A happens-before B 那么java内存模型将向程序员保证————A操作的结果一定对B操作可见且A的执行顺序一定在B的前面。第二条是JMM对编译器和处理器重排序的约束原则只要不改变程序的执行结果编译器和处理器怎么优化都行。
二、组成Happens-Before模型的八种规则
happens-before模型是JMM要求多个操作必须满足的关系模型而happens-before模型是由八条具体规则组成的具体如下
程序顺序规则as-if-serial语义一个线程中的每个操作happens-before于该线程的任意后续操作。监视器锁规则对一个锁的解锁happens-before于随后对这个锁的加锁。volatile变量规则对一个volatile域的写happens-before于任意后续对该volatile域的读。传递性规则如果A happens-before B且B happens-before C那么A happens-before C。start()规则 如果线程A执行ThreadB.start()那么A线程的ThreadB.start()操作happens-before于线程B的任意操作。join()规则 如果线程A执行ThreadB.join()那么B线程中的任意操作happens-before于线程A从ThreadB.join()成功返回。程序中断规则对线程interrupted()方法的调用happens-before与被中断线程的代码检测到中断时间的发生。对象finalize规则一个对象初始化完成构造函数执行结束happens-before于发生它的finalize()方法的开始。
2.1 程序顺序规则as-if-serial语义
不能改变程序的执行结果在单线程环境下执行的结果不变依赖问题 如果两个指令存在依赖关系不允许重排序
这样听起来好像happens-before和as-if-serial语义没什么区别但是一定要搞清楚as-if-serial是组成happens-before模型的其中一条规则两者是包含的关系下面对两者进行一个比较
as-if-serial语义保证单线程内程序的执行结果不被改变happens-before保证正确同步的多线程和单线程的执行结果不被改变。as-if-serial语义给编写单线程程序的程序员创造了一个幻境单线程程序是按程序的顺序来执行的。happens-before关系给编写正确同步的多线程程序的程序员创造了一个幻境正确同步的多线程程序是按happens-before指定的顺序来执行的。as-if-serial语义和happens-before这么做的目的都是为了在不改变程序执行结果的前提下尽可能地提高程序执行的并行度。
int a0;
int b0;
void test(){int a1; aint b1; bint ca*b; c
}
a happens -before b ; b happens before c
2.2 传递性规则
a happens-before b 且 b happens- before c那么 a happens-before c
2.3 volatile变量规则
volatile 修饰的变量的写操作一定happens-before后续对于volatile变量的读操作。该规则利用volatile关键字通过内存屏障机制来防止指令重排。 上图中的No表示不允许重排序由上图我们就知道了使用volatile可以保证有序性。
public class VolatileExample {int a 0;volatile boolean flag false;public void writer() {a 1; 1flag true; // 修改 2}public void reader() {if (flag) { // true 3// i的值最终一定会被设置为1int i a; 4}}
}
1 happens-before 2 - 因为程序顺序规则和volatile规则。
3 happens-before 4 - 因为程序顺序规则
2 happens-before 3 - 因为volatile规则
1 happens-before 4 - 因为传递性规则
基于上面的规则保证了最终i1成立。
这里重点讲一下上面的1 happens-before 2 为什么成立。在上面给出了volatile重排序规则表的图片其中有一条是代码中第一个操作是普通读写在上面代码中对应了a1第二个操作是volatile写在上面代码中对应了flagtrue这种情况是不允许重排序的所以1 happens-before 2成立。
2.4 监视器锁规则
int x 10;
synchronized(this) {// 后续线程读取到的x的值一定12if(x 12) {x 12;}
}
x 12;
2.5 start规则
public class StartDemo{int x 0;Thread t1 new Thread(()-{// 读取x的值 一定是20if(x 20){}});x 20;// t1.start()以及之前的所有操作都发生在t1线程中任意操作之前t1.start();
}
2.6 Join规则
public class Test{int x0;Thread t1new Thread(()-{// t1线程中的任意操作都发生在当前线程中t1.join成功返回之前x 200;});t1.start();t1.join(); //保证结果的可见性。//在此处读取到的x的值一定是200.
} 相关文章 【Java内存模型】Java内存模型JMM详解以及并发编程的三个重要特性原子性可见性有序性【并发编程】volatile关键字最全详解看这一篇就够了【并发编程】synchronized关键字最全详解看这一篇就够了