摘要:线程执行与变量可见性的关系什么是的关系的关系是保证一个线程执行的操作结果对不同线程中的另一个操作可见。执行写入和读取到内存的两个线程可以在时钟时间方面与其他操作保持一致,但可能看不到彼此一致的更改内存一致性错误,除非它们有关系。
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之前。
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/75687.html
摘要:举个例子,在多线程不使用环境中,每个线程会从主存中复制变量到缓存以提高性能。保证了变量的可见性关键字解决了变量的可见性问题。在多线程同时共享变量的情形下,关键字已不足以保证程序的并发性。 volatile 关键字能把 Java 变量标记成被存储到主存中。这表示每一次读取 volatile 变量都会访问计算机主存,而不是 CPU 缓存。每一次对 volatile 变量的写操作不仅会写到 ...
摘要:这个规则比较好理解,无论是在单线程环境还是多线程环境,一个锁处于被锁定状态,那么必须先执行操作后面才能进行操作。线程启动规则独享的方法先行于此线程的每一个动作。 1. 指令重排序 关于指令重排序的概念,比较复杂,不好理解。我们从一个例子分析: public class SimpleHappenBefore { /** 这是一个验证结果的变量 */ private st...
摘要:当线程执行完后进入状态,表示线程执行结束。其中和表示两个线程。但要注意,让出并不表示当前线程不执行了。关键字其作用是防止指令重排和使线程对一个对象的修改令其他线程可见。 JMM特性一览 Java Memory Model的关键技术点都是围绕着多线程的原子性、可见性和有序性来建立的。因此我们首先需要来了解这些概念。 原子性(Atomicity) 原子性是指一个操作是不可中断的。即使是在多...
阅读 1902·2021-11-15 11:46
阅读 1102·2021-10-26 09:49
阅读 1835·2021-10-14 09:42
阅读 3394·2021-09-26 09:55
阅读 845·2019-08-30 13:58
阅读 1045·2019-08-29 16:40
阅读 3481·2019-08-26 10:27
阅读 616·2019-08-23 18:18