共计 923 个字符,预计需要花费 3 分钟才能阅读完成。
Java 线程执行与变量可见性的 happen-before 关系
什么是 happen-before 的关系
happen-before 的关系是保证一个线程执行的操作结果对不同线程中的另一个操作可见。
Happens-before 定义程序中所有操作的部分排序。为了保证执行操作 Y 的线程可以看到操作 X 的结果(X 和 Y 是否出现在不同的线程中),X 和 Y 之间必然存在一个先发生的关系。在没有 happen-before 排序的情况下在两个操作之间,JVM 可以根据需要自由重新排序(JIT 编译器优化)。
happen-before 的不仅仅是 ’ 时间 ’ 中的动作重新排序,而且还保证了对内存的读写顺序。执行写入和读取到内存的两个线程可以在时钟时间方面与其他操作保持一致,但可能看不到彼此一致的更改(内存一致性错误),除非它们有 happen-before 关系。
如何建立 happen-before 关系?
以下是发生之前的规则:
- 单线程规则:单个线程中的每个操作都发生在该程序顺序中稍后出现的该线程中的每个操作之前。
- 监视器锁定规则:监视器锁定(退出同步方法 / 块)上的解锁发生 – 在每次后续获取同一监视器锁定之前。
- 易失性变量规则:在对该相同字段的每次后续读取之前发生对易失性字段的写入。易失性字段的写入和读取具有与进入和退出监视器(读取和写入时的同步块)类似的内存一致性效果,但实际上没有获取监视器 / 锁定。
- 线程启动规则:线程上的 Thread.start() 调用发生在启动线程中的每个操作之前。假设线程 A 通过调用 threadA.start() 生成一个新线程 B. 在线程 B 的 run 方法中执行的所有操作都将看到线程 A 调用 threadA.start() 方法,之前(仅在线程 A 中)发生在它们之前。
- 线程连接规则:线程中的所有操作都发生在任何其他线程从该线程上的连接成功返回之前。假设线程 A 通过调用 threadA.start() 生成一个新线程 B,然后调用 threadA.join()。线程 A 将在 join() 调用时等待,直到线程 B 的 run 方法完成。在 join 方法返回后,线程 A 中的所有后续操作都将看到线程 B 的 run 方法中执行的所有操作都发生在它们之前。
- 传递性:如果 A 发生在 B 之前,B 发生在 C 之前,那么 A 发生在 C 之前。
正文完