首页 > 图灵资讯 > java面试题>正文
金三银四精选java面试题-指令重排有限制吗?happens-before了解吗?
2024-01-01 19:22:04
指令重排有限制吗?happens-before了解吗?
指令重排也是有一些限制的,有两个规则happens-before和as-if-serial来约束。
happens-before的定义:
- 如果一个操作happens-before另一个操作,那么第一个操作的执行结果将对第二个操作可见,而且第一个操作的执行顺序排在第二个操作之前。
- 两个操作之间存在happens-before关系,并不意味着Java平台的具体实现必须要按照 happens-before关系指定的顺序来执行。只要没有改变程序的执行结果,编译器和处理器怎么优化都可以。
happens-before的六大规则:
- 程序顺序规则:一个线程中的每个操作,happens-before于该线程中的任意后续操作。
/**
* 顺序性规则
* 顺序执行是针对代码逻辑而言的,在实际执行的时候发生指令重排序但是并没有改变源代码的逻辑。
* @author 百里
*/
public class BaiLiHappenBeforeDemo {
public static void main(string[] args) {
double pi = 3.14; // A
double r = 1.0; // B
double area = pi * r * r; // C
System.out.println(area);
}
}
- 监视器锁规则:一个unlock操作之前对某个锁的lock操作必须发生在该unlock操作之前
import java.util.concurrent.locks.ReentrantLock;
/**
* 重排锁的话,会导致逻辑改变。
* @author 百里
*/
public class BaiLiHappenBeforeLockDemo {
public static void main(String[] args) {
ReentrantLock reentrantLock = new ReentrantLock();
reentrantLock.lock();
// TODO
reentrantLock.unlock();
reentrantLock.lock();
// TODO
reentrantLock.unlock();
}
}
- volatile变量规则:对一个volatile变量的写操作必须发生在该变量的读操作之前。
- 传递性规则:如果A happens-before B,且B happens-before C,那么A happens-before C。
从图中,我们可以看到:
- “x=42”Happens-Before 写变量“v=true”,这是规则1的内容;
- 写变量“v=true”Happens-Before 读变量“v=true”,这是规则3的内容;
- 再根据这个传递性规则,我们得到结果:“x=42”Happens-Before 读变量“v=true”;
这意味着什么呢?如果线程 B 读到了“v=true”,那么线程A设置的“x=42”对线程B是可见的。也就是说,线程B能看到“x == 42“。
/**
* 传递性规则
* @author 百里
*/
public class BaiLiHappenBeforeVolatileDemo {
int x = 0;
volatile boolean v = false;
public void writer() {
x = 42;
v = true;
}
public void reader() {
if (v == true) {
System.out.println(x);
}
}
}
- 线程启动规则:如果线程A执行操作ThreadB.start()(启动线程B),那么A线程的ThreadB.start()操作happens-before于线程B中的任意操作。
我们可以理解为:线程A启动线程B之后,线程B能够看到线程A在启动线程B之前的操作。
- 线程结束规则:如果线程A执行操作ThreadB.join()并成功返回,那么线程B中的任意操作 happens-before于 ThreadB.join()操作成功返回后的线程A操作。
在Java语言里面,Happens-Before的语义本质上是一种可见性,A Happens-Before B 意味着A事件对B事件来说是可见的,并且无论A事件和B事件是否发生在同一个线程里。