java内存模型中的happens-before的疑惑……

问题描述

我的问题有人提过,但是侧重点有不同,而且没人回答过:http://www.iteye.com/problems/54095jsr133里面定义到happens-before规则之一:“Each action in a thread happens-before every subsequent action in that thread.”,翻译过来就是:“线程中的每个操作都happens-before这个线程中后续的所有操作。”我们都知道为了效率问题,在编译,JIT和缓冲区这几个地方可能会发生代码的重排序问题。但是前面的happens-before的规则如果是这样的理解的话是禁止了重排序到发生。这很显然是有问题的。如上对happens-before的理解肯定是有问题的,所以,希望有兄弟能解释下这个happens-before规则到真正含义是什么? 问题补充:freish 写道

解决方案

我的理解是happens-before定义了几条规则,只有做了适当同步的代码才会遵循这几条规则,并不是所有的代码都遵循这个规则,如你提到的重排序问题
解决方案二:
有一个疑问,如果只有正确的同步的程序才具有happens-before关系,那怎么保证单线程程序在乱序的情况下结果是确定的?
解决方案三:
引用是不是因果关系反了? 做了适当同步的代码才会遵循这些happens-before规则,还是遵循了happens-before规则才算是适当同步的代码?不管这个因果关系吧,可以肯定的一点是,需要同步(包括synchronized关键字、volatile变量、final变量、java.util.concurrent.locks等)才能保证这样的关系
解决方案四:
由类库提供的具有happends-before关系的有:Placing an item in a thread-safe collection happens-before another thread retrieves that item from the collection;Counting down on a CountDownLatch happens-before a thread returns from await on that latch;Releasing a permit to a Semaphore happens-before acquiring a permit from that same Semaphore;Actions taken by the task represented by a Future happens-before another thread successfully returns from Future.get;Submitting a Runnable or Callable to an Executor happens-before the task begins execution; andA thread arriving at a CyclicBarrier or Exchanger happens-before the other threads are released from that same barrier or exchange point. If CyclicBarrier uses a barrier action, arriving at the barrier happens-before the barrier action, which in turn happens-before threads are released from the barrier.
解决方案五:
The JMM defines a partial ordering called happens-before on all actions within the program. To guarantee that the thread executing action B can see the results of action A (whether or not A and B occur in different threads), there must be a happens-before relationship between A and B. In the absence of a happens-before ordering between two operations, the JVM is free to reorder them as it pleases.A data race occurs when a variable is read by more than one thread, and written by at least one thread, but the reads and writes are not ordered by happens-before. A correctly synchronized program is one with no data races; correctly synchronized programs exhibit sequential consistency, meaning that all actions within the program appear to happen in a fixed, global order.综上,只有正确同步的程序才具有happens-before关系

时间: 2024-07-29 17:52:15

java内存模型中的happens-before的疑惑……的相关文章

在Java内存模型中测试并发程序代码_java

让我们来看看这段代码:   import java.util.BitSet; import java.util.concurrent.CountDownLatch; public class AnExample { public static void main(String[] args) throws Exception { BitSet bs = new BitSet(); CountDownLatch latch = new CountDownLatch(1); Thread t1 =

Java内存模型FAQ(九)在新的Java内存模型中,final字段是如何工作的

原文:http://www.cs.umd.edu/~pugh/java/memoryModel/jsr-133-faq.html 第九章 译者:Alex 一个对象的final字段值是在它的构造方法里面设置的.假设对象被正确的构造了,一旦对象被构造,在构造方法里面设置给final字段的的值在没有同步的情况下对所有其他的线程都会可见.另外,引用这些final字段的对象或数组都将会看到final字段的最新值. 对一个对象来说,被正确的构造是什么意思呢?简单来说,它意味着这个正在构造的对象的引用在构造期

聊聊我对Java内存模型的理解

所有的编程语言中都有内存模型这个概念,区别于微架构的内存模型,高级语言的内存模型包括了编译器和微架构两部分.我试图了解了Java.C#和Go语言的内存模型,发现内容基本大同小异,只是这些语言在具体实现的时候略有不同. 我们来看看Java内存模型吧,提到Java内存模型大家对这个图一定非常熟悉: 这张图告诉我们在线程运行的时候有一个内存专用的一小块内存,当Java程序会将变量同步到线程所在的内存,这时候会操作工作内存中的变量,而线程中变量的值何时同步回主内存是不可预期的.但同时Java内存模型又告

同步与Java内存模型(一)序言

原文:http://gee.cs.oswego.edu/dl/cpj/jmm.html 作者:Doug Lea 译者:萧欢  校对:丁一,方腾飞 先来看如下这个简单的Java类,该类中并没有使用任何的同步. 查看源代码 打印帮助 01 final class SetCheck { 02 private int  a = 0; 03 private long b = 0; 04   05 void set() { 06 a =  1; 07 b = -1; 08 } 09   10 boolean

全面理解Java内存模型

Java内存模型即Java Memory Model,简称JMM.JMM定义了Java 虚拟机(JVM)在计算机内存(RAM)中的工作方式.JVM是整个计算机虚拟模型,所以JMM是隶属于JVM的. 如果我们要想深入了解Java并发编程,就要先理解好Java内存模型.Java内存模型定义了多线程之间共享变量的可见性以及如何在需要的时候对共享变量进行同步.原始的Java内存模型效率并不是很理想,因此Java1.5版本对其进行了重构,现在的Java8仍沿用了Java1.5的版本. 关于并发编程 在并发

Java内存模型FAQ(三)JSR133是什么?

原文:http://www.cs.umd.edu/~pugh/java/memoryModel/jsr-133-faq.html 第三章 译者:Alex 从1997年以来,人们不断发现Java语言规范的17章定义的Java内存模型中的一些严重的缺陷.这些缺陷会导致一些使人迷惑的行为(例如final字段会被观察到值的改变)和破坏编译器常见的优化能力. Java内存模型是一个雄心勃勃的计划,它是编程语言规范第一次尝试合并一个能够在各种处理器架构中为并发提供一致语义的内存模型.不过,定义一个既一致又直

深入理解Java内存模型系列篇

[本文转载于深入理解Java内存模型,可点击每个章节标题查看原文] 深入理解Java内存模型(一)--基础 并发编程模型的分类 在并发编程中,我们需要处理两个关键问题:线程之间如何通信及线程之间如何同步(这里的线程是指并发执行的活动实体).通信是指线程之间以何种机制来交换信息.在命令式编程中,线程之间的通信机制有两种:共享内存和消息传递. 在共享内存的并发模型里,线程之间共享程序的公共状态,线程之间通过写-读内存中的公共状态来隐式进行通信.在消息传递的并发模型里,线程之间没有公共状态,线程之间必

深入理解Java内存模型(六)——final

与前面介绍的锁和volatile相比较,对final域的读和写更像是普通的变量访问.对于final域,编译器和处理器要遵守两个重排序规则: 在构造函数内对一个final域的写入,与随后把这个被构造对象的引用赋值给一个引用变量,这两个操作之间不能重排序. 初次读一个包含final域的对象的引用,与随后初次读这个final域,这两个操作之间不能重排序. 下面,我们通过一些示例性的代码来分别说明这两个规则: public class FinalExample { int i; //普通变量 final

Akka与Java内存模型的关系

原文链接:http://doc.akka.io/docs/akka/2.3.6/general/jmm.html   译者:clearity 不管你使用的Typesafe系统是Scala版本还是Java版本,都可以使你编写并发程序的过程变得更加容易.这篇文章主要讨论的是Typesafe系统,特别是针对Akka在并发程序中对共享内存的处理部分. Java内存模型 在之前的Java 5 版本中,Java内存模型的定义是很值得商榷的.以至于在共享内存环境下的多线程处理的结果变得多种多样,比如: 线程读