Java存储模型有一个happens-before原则,就是如果动作B要看到动作A的执行结果(无论A/B是否在同一个线程里面执行),那么A/B就需要满足happens-before关系。
在介绍happens-before法则之前介绍一个概念:JMM动作(Java Memeory Model Action),Java存储模型动作。一个动作(Action)包括:变量的读写、监视器加锁和释放锁、线程的start()和join()。后面还会提到锁的的。
happens-before完整规则:
(1)同一个线程中的每个Action都happens-before于出现在其后的任何一个Action。
(2)对一个监视器的解锁happens-before于每一个后续对同一个监视器的加锁。
(3)对volatile字段的写入操作happens-before于每一个后续的同一个字段的读操作。
(4)Thread.start()的调用会happens-before于启动线程里面的动作。
(5)Thread中的所有动作都happens-before于其他线程检查到此线程结束或者Thread.join()中返回或者Thread.isAlive()==false。
(6)一个线程A调用另一个另一个线程B的interrupt()都happens-before于线程A发现B被A中断(B抛出异常或者A检测到B的isInterrupted()或者interrupted())。
(7)一个对象构造函数的结束happens-before与该对象的finalizer的开始
(8)如果A动作happens-before于B动作,而B动作happens-before与C动作,那么A动作happens-before于C动作。
volatile语义
到目前为止,我们多次提到volatile,但是却仍然没有理解volatile的语义。
volatile相当于synchronized的弱实现,也就是说volatile实现了类似synchronized的语义,却又没有锁机制。它确保对volatile字段的更新以可预见的方式告知其他的线程。
volatile包含以下语义:
(1)Java 存储模型不会对valatile指令的操作进行重排序:这个保证对volatile变量的操作时按照指令的出现顺序执行的。
(2)volatile变量不会被缓存在寄存器中(只有拥有线程可见)或者其他对CPU不可见的地方,每次总是从主存中读取volatile变量的结果。也就是说对于volatile变量的修改,其它线程总是可见的,并且不是使用自己线程栈内部的变量。也就是在happens-before法则中,对一个valatile变量的写操作后,其后的任何读操作理解可见此写操作的结果。
尽管volatile变量的特性不错,但是volatile并不能保证线程安全的,也就是说volatile字段的操作不是原子性的,volatile变量只能保证可见性(一个线程修改后其它线程能够理解看到此变化后的结果),要想保证原子性,目前为止只能加锁!
volatile通常在下面的场景:
volatile boolean done = false;
while( ! done ){
dosomething();
}
应用volatile变量的三个原则:
(1)写入变量不依赖此变量的值,或者只有一个线程修改此变量
(2)变量的状态不需要与其它变量共同参与不变约束
(3)访问变量不需要加锁
分享到:
相关推荐
### Happens-Before原则详解 #### 一、引言 Happens-before原则是Java并发编程中的一个重要概念,用于描述程序中的操作之间的顺序关系。它不仅有助于理解和解决并发编程中的可见性问题,还为程序员提供了关于多...
"浅谈Java内存模型之happens-before" Java内存模型是Java虚拟机中的一种机制,用于定义Java程序中线程之间的内存访问方式。在多线程环境下,线程之间的通信和数据共享是非常复杂的,需要有一些规则来保证数据的一致...
"深入浅出了解happens-before原则" 在 Java 内存模型(JMM)中,happens-before 原则是一个核心概念,它规定了多线程环境下的可见性原则。该原则的核心思想是:两个操作之间的 happens-before 关系,并不意味着前一...
Java内存模型中的happens-before和重排序 Java内存模型(JMM)是Java虚拟机(JVM)中的一种抽象模型,用于描述Java程序中的内存交互。其中,happens-before关系是JMM中的一种基本概念,用于描述操作之间的顺序关系...
为了解决这个问题,Java引入了"happens-before"原则,它是一种确保正确同步和数据可见性的规则。 1. **程序顺序规则**: 这个规则指出,在同一线程内,程序中表现出的顺序应该被维护,即每个操作`happens-before`...
Java内存模型(JMM)及happens-before原理 Java内存模型(JMM)是Java虚拟机(JVM)中的一组规则,用于定义 Java 程序中的内存访问顺序。它规定了在多线程环境中,变量的写入操作对其他线程的可见性。JMM的主要目的是...
在Java并发编程中,理解和掌握volatile关键字以及happens-before原则对于解决内存一致性错误至关重要。内存一致性错误通常出现在多线程环境下,当不同线程访问共享变量时,由于缓存和处理器优化,可能导致数据不一致...
"锁的释放-获取建立的happens before关系"是指在并发执行的线程之间,当一个线程释放锁之后,另一个线程获取同一把锁时,它们之间存在一种特定的内存可见性保证。这种关系是由Java内存模型(Java Memory Model,JMM...
shift-happens---依旧大师级
在Java 5及以后的版本中,引入了happens-before原则,来保证并发程序的正确性。 happens-before原则是Java内存模型中的一个重要概念,它定义了两个操作之间的内存可见性。如果操作X happens-before 操作Y,那么X对Y...
下面介绍几个与理解 ConcurrentHashMap 有关的 happens-before 关系法则: * 程序次序法则:如果在程序中,所有动作 A 出现在动作 B 之前,则线程中的每动作 A 都 happens-before 于该线程中的每一个动作 B。 * ...
4. 传递性:如果 A happens-before B,且 B happens-before C,那么 A happens-before C。 5. 线程启动规则:Thread 对象的 start()方法 happens-before 于此线程的每一个动作。 Volatile 和 Synchronized ...
4. 传递性:如果A happens-before B,B happens-before C,则A happens-before C。 5. start()规则:启动线程B的操作发生在B线程内任何操作之前。 6. join()规则:线程A成功等待线程B结束,B线程内的所有操作发生在A...
本篇文章将深入探讨Java锁的释放与建立,以及它们之间的_happens-before_关系,旨在帮助开发者更好地理解和应用并发控制。 首先,Java中的锁主要包括两种类型:内置锁(也称为监视器锁)和显式锁。内置锁是通过`...
3. **Happens-Before规则**:Happens-Before是JMM的核心概念,它定义了两个操作之间的顺序关系,确保一个操作的结果能被另一个操作观察到。主要规则包括程序顺序、锁的释放与获取、volatile变量的写读、线程启动、...
* 传递性:A happens-before B,B happens-before C,则A happens-before C。 * start()规则:如果线程A执行ThreadB.start()那么ThreadB.start() happens-before线程B中任何操作。 * join()规则:如果线程A执行...
从标签来看,文档会涉及如JSR(Java Specification Request)、内存模型、线程规范以及happens-before原则和synchronized关键字。这些词汇暗示了文档将对Java内存模型进行深入讲解,并探讨多线程环境下的线程通信和...
happens-before原则是Java内存模型中定义的两项操作之间的偏序关系,如果说操作A先行发生于操作B,其实就是说在发生操作B之前,操作A产生的影响能被操作B观察到。“影响”包括修改了内存中共享变量的值、 发送了消息...
本文从Java多线程的基本概念开始,逐步深入到Java多线程的高级话题,涵盖了Java多线程的所有方面,包括volatile关键字、Java内存模型、Happens-Before关系、synchronized关键字、ConcurrentHashMap、...