java指令重排序问题 [问题点数:50分]

Bbs1
本版专家分:0
结帖率 33.33%
Bbs6
本版专家分:8704
Blank
蓝花 2017年7月 Java大版内专家分月排行榜第三
Bbs5
本版专家分:2685
Bbs2
本版专家分:335
Bbs5
本版专家分:3545
Java基础: 什么是指令重排序/as-if-serial/内存屏障/happens-before
Java基础知识<em>指令</em><em>重排序</em>在执行程序时,为了提高性能,编译器和处理器会对<em>指令</em>做<em>重排序</em>。编译器优化<em>重排序</em>:编译器在不改变单线程程序语义的前提下,可以重新安排语句的执行顺序。<em>指令</em>级并行的<em>重排序</em>:如果不存l在数据依赖性,处理器可以改变语句对应机器<em>指令</em>的执行顺序。内存系统的<em>重排序</em>:处理器使用缓存和读写缓冲区,这使得加载和存储操作看上去可能是在乱序执行。但是,可以通过插入特定类型的Memory Barrie...
Java JVM(十二):指令重排序
介绍<em>指令</em><em>重排序</em>的相关知识。
java synchronized具有禁止重排序功能
1.结论我们知道volatile关键字具有禁止<em>指令</em><em>重排序</em>的功能,而且能保证可见性,但不能保证原子性。synchronized关键字则不仅仅能保证可见性,还能保证原子性,那么synchronized关键字是否像volatile那样具有禁止<em>指令</em><em>重排序</em>的功能呢?答案是肯定的,synchronized具有禁止<em>重排序</em>功能。2.论据出处查找国内文档,发现基本对synchronized的描述很少提及禁止<em>重排序</em>的问
多线程之指令重排序
1、首先为何要<em>指令</em><em>重排序</em>(instruction reordering)? 编译器或运行时环境为了优化程序性能而采取的对<em>指令</em>进行重新排序执行的一种手段。 也就是说,对于下面两条语句: int a = 10; int b = 20; 在计算机执行上面两句话的时候,有可能第二条语句会先于第一条语句执行。所以,千万不要随意假设<em>指令</em>执行的顺序。 2、是不是所有的语句的执行顺
深入分析Volatile的实现原理
1、引言在多线程并发编程中synchronized和Volatile都扮演着重要的角色,Volatile是轻量级的synchronized,它在多处理器开发中保证了共享变量的“可见性”。可见性的意思是当一个线程修改一个共享变量时,另外一个线程能读到这个修改的值。它在某些情况下比synchronized的开销更小,下面我们将深入分析Voliate的实现原理。2、Volatile定义<em>java</em>编程语言允许
voliate
线程不可见的原因 线程交叉执行 <em>重排序</em>结合线程交叉执行 享变量更新后的值没有在工作内存与主存间及时更新 voliate 通过内存屏障 和 禁止<em>重排序</em>优化 来实现的 对voliate进行写操作时 会在写操作后加一条 store 屏障<em>指令</em>,将本地内存中的变量刷新到 主内存 对voliate时行读操作时,会在读操作后加一条 load 屏障<em>指令</em>,从主内存中读取共享变量的值 禁止<em>重排序</em> 关于禁止<em>指令</em>...
关于内存屏障
请教高手们,linux中有内存屏障机制,barrier() ,mb(),等,小弟有一事不明,按照内存屏障的设计理念,是为了防止CPU乱序执行或者由于编译优化而导致有些命令执行顺序与希望的不一致,小弟的
java中voliate的讲解
Java并发编程:volatile关键字解析    volatile这个关键字可能很多朋友都听说过,或许也都用过。在Java 5之前,它是一个备受争议的关键字,因为在程序中使用它往往会导致出人意料的结果。在Java 5之后,volatile关键字才得以重获生机。   volatile关键字虽然从字面上理解起来比较简单,但是要用好不是一件容易的事情。由于volatile关键字是与Java
JAVA并发理解之重排序问题
       首先我们先来了解一下什么是<em>重排序</em>:<em>重排序</em>是指编译器和处理器为了优化程序性能而对<em>指令</em>序列进行重新排序的一种手段。从Java源代码到最终实际执行的<em>指令</em>序列,会分别经历下面3种<em>重排序</em>,如下图所示      上述的1属于编译器<em>重排序</em>,2和3属于处理器<em>重排序</em>。这些<em>重排序</em>可能会导致多线程程序出现内存可见性<em>问题</em>。在单线程程序中,对存在控制依赖的操作<em>重排序</em>,不会改变执行结果(这也是as-if-ser...
从 DCL(双重检查锁定)谈 volatile 禁止指令重排序
最近在看《Java并发编程的艺术》,看到双重检查锁定里谈到用 volatile 来解决创建对象时,<em>指令</em><em>重排序</em>的<em>问题</em>,想了解清楚为什么 volatile 可以禁止<em>指令</em><em>重排序</em>,结果得到了出乎意料的答案。
Java重排序对多线程的影响
上一次的发文远在两个月前了,算是经历了一段低糜期,本来打算的更新一直断更到现在。还是好好学习吧,努力的人运气一定不会差的。这一篇文章来谈一谈Java虚拟机对代码优化带来的影响吧。我们知道无论什么语言,最后驱动计算机的那一定是汇编,Java代码编译后会变成一段字节码,通过Java虚拟机的类加载机制ClassLoader加载到虚拟机里面,最后便是把它转化成汇编<em>指令</em>。通过JMM(Java内存模型)实现内存
说说Java中原子性,可见性与指令重排序的理解
原子性:就是读数据,处理数据,写数据 这三个步骤不能被终止,或者打断;就是不能被线程调度器中断,切换线程。 这样,才能保证,原子操作在切成切换,并行处理上保证数据地顺序累加处理。 可见性:是Jvm较为突出的概念,其每一个线程有自己的工作内存空间,当某一个线程读取了主内存的数据,那么会通知其他线程中自己的内存空间此数据被加屏障,不可读;只能再次从主内存读数据缓存到自己的内存空间。 <em>指令</em>
Java设计模式:单例模式+volatile禁止指令重排序
来自https://mp.weixin.qq.com/s/zn8e7nKUPXq4G4CzyE7rPA本文将会用到的关键词:单例:Singleton实例:instance同步:synchronized类装载器:ClassLoader单例模式:单例,顾名思义就是只能有一个、不能再出现第二个。就如同地球上没有两片一模一样的树叶一样。在这里就是说:一个类只能有一个实例,并且整个项目系统都能访问该实例。单...
原子性、内存可见性和重排序——重新认识synchronized和volatile
原子性、内存可见性和<em>重排序</em>——重新认识synchronized和volatile 一、原子性 原子性操作指相应的操作是单一不可分割的操作。例如,对int变量count执行count++d操作就不是原子性操作。因为count++实际上可以分解为3个操作:(1)读取变量count的当前值;(2)拿count的当前值和1做加法运算;(3)将加完后的值赋给count变量。 在多线程环境中
原子操作,内存可见性与指令重排序
&quot;原子操作(atomic operation)是不需要synchronized&quot;,这是Java多线程编程的老生常谈了。所谓原子操作是指不会被线程调度机制打断的操作;这种操作一旦开始,就一直运行到结束,中间不会有任何 context switch (切 换到另一个   原子操作       原子操作(atomic operation),是指不会被线程调度机制打断的操作;这种操作一旦开始,就一直...
volatile和重排序得一些小疑问
http://yeziwang.iteye.com/blog/1042492  好吧,这里我只想说说volatile在JMM中的语义。     当我们在使用volatile的时候,实际上它表达了下面那么些意思。      1. 可见性。       这个是大多数人都知道的一个特质, JAVA的线程有自己的工作内存区,与主存区不同,当我们对变量使用了volatile后,那么不管对这个...
java中的final对重排序的限制与逸出
在<em>java</em>中,为了保证final域的正确使用,对<em>重排序</em>进行了一些限制1.在构造函数内对一个final域的写入,与随后把这个被构造对象的引用赋值给一个引用变量,这两个操作之间不能<em>重排序</em>2.初次读一个包含final域的对象的引用,与随后初次读这个final域,这两个操作之间不能<em>重排序</em>    有了这个限制,如下A,B线程分别调用writer和reader方法时,可以保证final变量被初始化了 publ...
Java并发编程系列之三:重排序与顺序一致性
前言在我们编写程序并运行的时候,编译器给我们一个错觉:程序编译的顺序与编写的顺序是一致的。但是实际上,为了提高性能,编译器和处理器常常会对<em>指令</em>进行<em>重排序</em>。<em>重排序</em>主要分为两类:编译器优化的<em>重排序</em>、<em>指令</em>级别并行的<em>重排序</em>和内存系统的<em>重排序</em>。所以我们编写好Java源代码之后,会经过以上三个<em>重排序</em>,到最终的<em>指令</em>序列。我们这里提到的Java内存模型又是什么呢?Java内存模型(后面简称JMM)是语言级别的内存模
不得不提的volatile及指令重排序(happen-before)
转:http://www.th7.cn/Program/<em>java</em>/201312/166504.shtml 一、不得不提的volatile volatile是个很老的关键字,几乎伴随着JDK的诞生而诞生,我们都知道这个关键字,但又不太清楚什么时候会使用它;我们在JDK及开源框架中随处可见这个关键字,但并发专家又往往建议我们远离它。比如Thread这个很基础的类,其中很重要的线程状
【死磕Java并发】-----Java内存模型之重排序
在执行程序时,为了提供性能,处理器和编译器常常会对<em>指令</em>进行<em>重排序</em>,但是不能随意<em>重排序</em>,不是你想怎么排序就怎么排序,它需要满足以下两个条件: 1. 在单线程环境下不能改变程序运行的结果; 2. 存在数据依赖关系的不允许<em>重排序</em>如果看过LZ上篇博客的就会知道,其实这两点可以归结于一点:无法通过happens-before原则推导出来的,JMM允许任意的排序。as-if-serial语义as-if-se
Java的重排序影响线程调用顺序
你所认为的程序运行顺序是什么样的呢?是JVM照着程序编写的顺序运行吗?   正确答案是:不是的。
volatile关键字作用与内存可见性、指令重排序概述[JAVA]
在理解volotile关键字的作用之前,先粗略解释下内存可见性与<em>指令</em><em>重排序</em>。1. 内存可见性Java内存模型规定,对于多个线程共享的变量,存储在主内存当中,每个线程都有自己独立的工作内存,并且线程只能访问自己的工作内存,不可以访问其它线程的工作内存。工作内存中保存了主内存中共享变量的副本,线程要操作这些共享变量,只能通过操作工作内存中的副本来实现,操作完毕之后再同步回到主内存当中,其JVM内存模型大
什么是重排序问题
十七、 什么是<em>重排序</em><em>问题</em>Java内存模型中,允许编译器和处理器对<em>指令</em>进行<em>重排序</em>,但是<em>重排序</em>可以保证最终执行的结果是与程序顺序执行的结果一致,并且只会对不存在数据依赖性的<em>指令</em>进行<em>重排序</em>,这个<em>重排序</em>在单线程下对最终执行结果是没有影响的,但是在多线程下就会存在<em>问题</em>。一个例子int a = 1;(1) int b = 2;(2) int c= a + b;(3) 如上c的值依赖a和b的值,所以<em>重排序</em>后能够
关于一个可见性和指令重排序的例子
<em>java</em> cocurrency in practicepublic class NoVisibility { private static boolean ready; private static int number; private static class ReaderThread extends Thread{ public void run(){
编译器指令重排序 和 Java 内存模型
一,编译器<em>指令</em><em>重排序</em> 编译器在不影响 程序执行的结果下,可能对代码执行的先后顺序进行调整; 如: 以下代码 第二条可能会比第一条先执行; int a=1;  //&1 int b=2; //&  2 以下代码会顺序执行,不会改变顺序,因为第二条<em>指令</em>依赖第一条<em>指令</em>的结果 int a=1; int b=a+1; 看以下代码如下: public cl
Java中 volatile关键字怎么禁止重排序
使用volatile关键字修饰共享变量可以禁止<em>重排序</em>。若用volatile修饰共享变量,在编译时,会在<em>指令</em>序列中插入内存屏障来禁止特定类型的处理器<em>重排序</em>   volatile禁止<em>指令</em><em>重排序</em>的一些规则:   1.当第二个操作是voaltile写时,无论第一个操作是什么,都不能进行<em>重排序</em>   2.当地一个操作是volatile读时,不管第二个操作是什么,都不能进行<em>重排序</em>   3.当第一个操作是
doublecheck单例由于指令重排产生的问题
转自https://blog.csdn.net/anjxue/article/details/51038466 在阅读之前,请先了解下线程并发涉及到的三个概念:原子性、可见性、有序性,可以看下这篇文章:http://www.cnblogs.com/dolphin0520/p/3920373.html 我假设你已经看过几篇double check的文章,但还是一知半解。 我们先看这种双重检...
Java volatile 怎么保证不被指令重排序优化
内存间交互操作lock: 作用主内存unlock: 作用主内存read/load:这两个操作顺序执行,不能单独出现;主内存的变量=&amp;gt;工作内存的变量use: 作用工作内存,把工作内存变量传给执行引擎assign: 作用工作内存,把执行引擎收到的值赋给工作内存变量store/write: 这两个操作顺序执行;不能单独出现;工作内存的变量=&amp;gt;主内存的变量通过主内存与工作内存交互来理解这些操作...
Java 指令重排序与并发
一、<em>指令</em><em>重排序</em>: 编译器或运行时环境 为了优化程序性能而采取的对<em>指令</em>进行重新排序执行的一种手段。<em>指令</em><em>重排序</em>发生在不影响语义的情况下,也就是在 单线程下,<em>重排序</em>不能导致运行结果发生变化。(即遵循as-if-serial语义)进一步解释就是在不影响执行结果的情况下,代码在jvm内的执行顺序并不是严格按照书写顺序的,出于性能方面的考虑,jvm会对它进行<em>重排序</em>。如果两个操作访问同一个变量,且这两个变量有一...
从单例模式挖到内存模型(二)----指令重排序
首先是一个双检锁写的单例模式的例子: public class Single{ private volatile static Single single; private Single(){} public static Single getInstance(){ if(single==null){ synchronized (Single.class) { if(si
为啥要指令重排序
我们知道<em>java</em>在运行的时候有两个地方可能会把<em>指令</em><em>重排序</em>, 一个是编译器编译的的时候,一个是处理器运行的时候。 那么为啥要用<em>指令</em><em>重排序</em>呢? 编译期<em>重排序</em>有啥好处? CPU计算的时候要访问值,如果常常利用到寄存器中已有的值就不用去内存读取了,比如说 int a = 1; int b = 1; a = a + 1; b = b +1 ; 就可能没有 int a = 1; a = a ...
JVM系列 : 字节码、指令重排序
字节码简介 1.计算机只能识别0 1 , 经过0 1的组合 , 产生了数字 , 0 1组合也产生了各种字符 , 各种机器<em>指令</em> 2.不同的时代 , 不同产商 , 机器<em>指令</em>集(arm , x86 , rsic ...)是不同的 3.CPU与<em>指令</em>集直接耦合 , 一个程序要在多个平台运行 , 需要多套代码 4.如何实现跨平台 , 中间码(字节码)应运而生 字节码实际应用 1.字节码是JVM里指...
并发中的陷阱-处理器重排序
假设有两个线程分别调用同一个test对象的writer()和reader()。请问,console输出的是什么?(a) 0 (b) 1 (c) 不确定 (d) 不知道 public class test{ private boolean flag = false; private int a = 0; public void writer(){ a
重排序引起的内存可见性问题
什么是<em>重排序</em> 什么是内存可见性 将产生的<em>问题</em> 如何解决<em>问题</em> 什么是<em>重排序</em> <em>重排序</em>是指编译器和处理器为了优化程序性能而对<em>指令</em>序列进行重新排序的一种优化措施 如果两个操作访问同一个变量,且这两个操作有一个为写操作,此时这两个操作之间就存在数据依赖性数据依赖性可概括为以下三种类型: 上面三种情况,只要<em>重排序</em>两个操作的执行顺序,程序的结果就会被改变。在Java内存模型(以下...
JAVA 基础系列之 重排序和Volatile
<em>重排序</em>在执行程序时,编译器和处理器会对<em>指令</em>进行<em>重排序</em>,<em>重排序</em>分为: 编译器<em>重排序</em>:在不改变代码语义的情况下,优化性能而改变了代码执行顺序; <em>指令</em>并行的<em>重排序</em>:处理器采用并行技术使多条<em>指令</em>重叠执行,在不存在数据依赖的情况下,改变机器<em>指令</em>的执行顺序; 内存系统的<em>重排序</em>:使用缓存和读写缓冲区时,加载和存储可能是乱序执行。 比如现在有一段代码如下:a = 1; //代码1 b = 1; //代码2编译器和处
“双重检验锁失效”的问题说明
双重检验锁是一个高效的懒加载方法,被广泛引用或应用于多线程环境中。但是,在Java中,如果没有额外的同步,它并不能以独立的方式可靠地工作。当在其它语言上时,比如C++,它依赖于处理器的内存模型,编译器<em>重排序</em>以及编译器和同步库的交互。由于C++并没有对以上内容作出具体说明,所以很难说明在什么情况下双重检验锁会正常运行。在C++中可以显式地使用内存屏障
java内存屏障和重排序问题
<em>java</em>内存屏障和<em>重排序</em><em>问题</em>
Java内存模型中的重排序
<em>重排序</em>是指编译器和处理器为了优化程序性能而对<em>指令</em>序列进行重新排序的一种手段。 但是不能随时随地的<em>重排序</em>,我们可以看一个例子看待这个<em>问题</em>。 上面三种情况,只要<em>重排序</em>两个操作的执行顺序,那么程序的结果就会被改变。 所以 <em>重排序</em>需要遵守一些规则。 a、编译器和处理器不会改变存在数据依赖性关系的两个操作的执行顺序 b、单线程下,不能改变数据的执行结果 一、数据依赖性 在上面的情况中,我们...
JMM——重排序与内存屏障
<em>重排序</em> 在执行程序时为了提高性能,编译器和处理器常常会对<em>指令</em>做<em>重排序</em> <em>重排序</em>有三种类型: 1.编译器优化的<em>重排序</em> 编译器在不改变单线程程序语义的前提下,可以重新安排语句的执行顺序 2.<em>指令</em>级并行的<em>重排序</em> 现代处理器采用了<em>指令</em>级并行技术来将多条<em>指令</em>重叠执行。 如果不存在数据依赖性,处理器可以改变语句对应机器<em>指令</em>的执行顺序 3.内存系统的<em>重排序</em> 由于处理器使用缓存和读/写缓冲区,这使
聊聊并发:(六)指令重排序与happens-before原则分析
前言 在前几章中,我们介绍了线程安全相关的关键字synchronized与volatile的使用,在介绍其原理的过程中,我们提及到了Java中的“happen-before”规则,这个规则对于我们理解Java多线程开发非常的有用,本文我们就来了解一下什么是happen-before规则。 什么是happen-before? 在上一篇我们介绍volatile实现机制的时候,在<em>指令</em><em>重排序</em>的部...
Volatile 以DCL失效谈内存屏障用来禁止指令重排序的原理
引言 大家都知道volatile关键字具有两重语义即: 1)保证了不同线程对这个变量进行操作时的可见性,即一个线程修改了某个变量的值,这新值对其他线程来说是立即可见的。 2)禁止进行<em>指令</em><em>重排序</em>。 第一个好理解,也就是说每次修改都立即更新到主内存,那么禁止<em>重排序</em>这个在网上更多的解释是说使用了内存屏障,使得前后的<em>指令</em>无法进行<em>重排序</em>。(关于volatile详解) 那么<em>问题</em>来了,什么是内存屏障?...
JVM指令重排导致Singleton双重锁定出错
<em>指令</em>重排导致单例模式失效 我们都知道一个经典的懒加载方式的单例模式: public class Singleton { private static Singleton instance = null; private Singleton() { } public static Singleton getInstance() { if(instance == n
volatile是怎么保障内存可见性以及防止指令重排序的?
1、内存可见性 首先,要明确一下这个内存的含义,内存包括共享主存和高速缓存,Volatile关键字标识的变量,是指CPU从缓存读取数据时,要判断数据是否有效,如果缓存没有数据,则再从主存读取,主存就不存在是否有效的说法了。而内存一致性协议也是针对缓存的协议。 内存可见性意思是:一个CPU核心对数据的修改,对其他CPU核心立即可见。 这句话拆开了理解,CPU修改数据,首先是对缓存的修改,然后再...
java从源代码到指令序列的重排序
啊大苏打
volatile的指令重排序理解
volatile的实现逻辑涉及的是<em>指令</em><em>重排序</em>原理,下面对该关键字不同情况下的<em>指令</em><em>重排序</em>做点简单的分析. 先上一个表格列出各种<em>重排序</em>规则. 对上面这个表格的分析如下: 1.两个操作都是普通读和写,没有volatile要求,可以<em>重排序</em> 2.如果<em>重排序</em>,操作2(volatile读主内存)排在操作1的读和写之前:   2-1. 操作2(volatile读主内存) -&amp;gt; 操作1(普通读本地内...
03.(多线程与并发)面试题-02--Volidate的原理和指令重排序
线程栈(线程的工作内存)保存了线程运行时候变量值信息。当线程访问某一个对象时候值的时候,首先通过对象的引用找到对应在堆内存的变量的值,然后把堆内存变量的具体值load到线程本地内存中,建立一个变量副本,之后线程就不再和对象在堆内存变量值有任何关系,而是直接修改副本变量的值,   在修改完之后的某一个时刻(线程退出之前),自动把线程变量本的值回写到对象在堆中变量。这样在堆中的对象的值就产生变化
JVM的重排序问题
<em>重排序</em>通常是编译器或运行时环境为了优化程序性能而采取的对<em>指令</em>进行重新排序执行的一种手段。<em>重排序</em>分为两类:编译期<em>重排序</em>和运行期<em>重排序</em>,分别对应编译时和运行时环境。 特别是多个线程同时修改同一变量时,必须采取可靠的同步或其它措施保障数据被正确地修改,这里的一条重要原则是:不要假设<em>指令</em>执行的顺序,你无法预知不同线程之间的<em>指令</em>会以何种顺序执行。 但是在单线程程序中,通常我们容易假设<em>指令</em>是顺序执行的,否
为什么要指令重排序和屏障的作用
内存屏障是一个很神奇的东西,之前翻译了linux内核文档memory-barriers.txt,对内存屏障有了一定有理解。现在用自己的方式来整理一下。 在我看来,内存屏障主要解决了两个<em>问题</em>:单处理器下的乱序<em>问题</em>和多处理器下的内存同步<em>问题</em>。 为什么会乱序 现在的CPU一般采用流水线来执行<em>指令</em>。一个<em>指令</em>的执行被分成:取指、译码、访存、执行、写回、等若干个阶段。然后,多条<em>指令</em>可以同时存在于流水
Java - 指令重排序
为什么会发生<em>指令</em><em>重排序</em>(instruction reordering) 编译器或运行时环境为了优化程序性能而采取的对<em>指令</em>进行重新排序执行的一种手段。 也就是说对于下面的语句: int a = 10; int b = 20; 在计算机执行上面两句话的时候,有可能第二条语句会先于第一条语句执行。 然而并不是所有的<em>指令</em>都能重排,重排需要基于数据依赖性。 数据依赖性 如果两个操作访问...
happens-before,内存重排序,数据依赖的理解
在JMM(Java内存模型)中,如果一个操作执行的结果需要对另一个操作可见,那么这两个操作之间必须存在happens-before关系。 happens-before原则规则: 程序次序规则:一个线程内,按照代码顺序,书写在前面的操作先行发生于书写在后面的操作; 锁定规则:一个unLock操作先行发生于后面对同一个锁的lock操作; volatile变量规则:对一个变量的写操作先行发生于后...
深入理解java内存模型02-重排序
转载自并发编程网 – ifeve.com本文链接地址: 深入理解Java内存模型 硬件的效率一致性 高速缓存 &amp;amp;amp;amp;amp;amp;amp;amp;amp;amp; 缓存一致性 由于计算机的存储设备和处理器的运算速度有几个数量级的差距,所以现代计算机系统都不得不加入一层读写速度尽可能接近处理器的高速缓存(Cache)来作为内存与处理器之间的缓冲;将运算需要使用到的数据复制到缓存中,让运算能快速进行,当运算结束后在从缓存同步...
java指令重排序问题
转载:http://my.oschina.net/004/blog/222069?fromerr=ER2mp62C <em>指令</em><em>重排序</em>是个比较复杂、觉得有些不可思议的<em>问题</em>,同样是先以例子开头(建议大家跑下例子,这是实实在在可以重现的,<em>重排序</em>的概率还是挺高的),有个感性的认识 /** * 一个简单的展示Happen-Before的例子. * 这里有两个共享变量:a和flag,初始值分别为0和fal
指令重排序
<em>指令</em><em>重排序</em> 对主存的一次访问一般花费硬件的数百次时钟周期。处理器通过缓存(caching)能够从数量级上降低内存延迟的成本这些缓存为了性能重新排列待定内存操作的顺序。也就是说,程序的读写操作不一定会按照它要求处理器的顺序执行。 <em>重排序</em>的背景 我们知道现代CPU的主频越来越高,与cache的交互次数也越来越多。当CPU的计算速度远远超过访问cache时,会产生cache wai
CPU指令重排与缓存一致性
程序中CPU计算+与内存交互(读取,赋值),CPU计算速度远远高于与内存交互的速度(好比内存与查数据库)引入缓存提高速度,缓存一致性是保证数据准确性的硬件协议。<em>指令</em>重排无法逾越内存屏障。 缓存一致性的实现,先看看x86的cpu缓存结构。 1、各种寄存器,用来存储本地变量和函数参数,访问一次需要1cycle,耗时小于1ns; 2、L1 Cache,一级缓存,本地core的缓存,分成32K的数据缓存...
Java多线程--重排序与顺序一致性
前言 在我们编写程序并运行的时候,编译器给我们一个错觉:程序编译的顺序与编写的顺序是一致的。但是实际上,为了提高性能,编译器和处理器常常会对<em>指令</em>进行<em>重排序</em>。<em>重排序</em>主要分为两类:编译器优化的<em>重排序</em>、<em>指令</em>级别并行的<em>重排序</em>和内存系统的<em>重排序</em>。所以我们编写好Java源代码之后,会经过以上三个<em>重排序</em>,到最终的<em>指令</em>序列。我们这里提到的Java内存模型又是什么呢?Java内存模型(后面简称JMM)是语言级
Java单例的由浅入深----懒汉式的升级(2 原子操作、指令重排)懒汉式的最终版本(volatile)
知识点:什么是原子操作简单的来说,原子操作(atomic)就是不可分割的操作,在计算机中,就是指不会因为线程调度被打断的操作。 比如,简单的赋值就是一个原子操作m=6;例如m原先的值为0,那么对于这个操作,要么执行成功变成了6,要么执行失败变成了0,而不会出现诸如m=3这种中间状态–即使是在并发的线程中。 然而声明赋值就不是一个原子操作:int m = 6;对于这个语句,至少有两个操作: 1、
Final域的重排序规则
*摘自《Java并发编程的艺术》——方腾飞 1.final类型为基本类型时 对于final域,编译器和处理器要遵守两个<em>重排序</em>规则。 1)在构造函数内对一个final域的写入,与随后把这个被构造对象的引用赋值给一个引用变量,这两个操作之间不能<em>重排序</em>。 2)初次读一个包含final域的对象的引用,与随后初次读这个final域,这两个操作之间不能<em>重排序</em>。 总结来说,对final域的写入操作(初始化...
从单例模式的Double-Check看指令重排
晚上同学问了我一个<em>问题</em>,单例模式的Double-Check机制在多线程模式是否会出现<em>问题</em>。这个<em>问题</em>我当时有些琢磨不透,晚上翻阅书籍记录一下这个<em>问题</em>的收获。  public class Singleton { public static Singleton instance; private Singleton(){}; public static Singleton getInst
volatile及指令重排序
一、不得不提的volatile   volatile是个很老的关键字,几乎伴随着JDK的诞生而诞生,我们都知道这个关键字,但又不太清楚什么时候会使用它;我们在JDK及开源框架中随处可见这个关键字,但并发专家又往往建议我们远离它。比如Thread这个很基础的类,其中很重要的线程状态字段,就是用volatile来修饰,见代码   /* Java thread status for tool
多线程之重排序详解
<em>重排序</em> <em>重排序</em>是指编译器和处理器为了优化程序性能而对<em>指令</em>序列进行重新排序的一种手段。 数据依赖性 如果两个操作访问同一个变量,且这两个操作中有一个为写操作,此时这两个操作之间就存在数据的依赖性。数据依赖分为3中类型,如下表所示: 上面3中情况,只要<em>重排序</em>两个操作的顺序。程序的结果就会改变。编译器和处理器是可以对操作进行<em>重排序</em>的,在<em>重排序</em>时,会遵守数据依赖性,编译器和处理器不会改变存在数...
voliate禁止重排序
会插入一个storestore的屏障 禁止上面的普通写 与 下面的voliate写 进行<em>重排序</em> 之后再会插入一个 soreLoad的屏障 禁止上面的 voliate写与下面有可以有的voliate读写进行<em>重排序</em>...
你以为在java里用synchronized就能万事大吉了吗?
我们先来想想,synchronized的功能: 1.同步,搞互斥锁,使线程不能交叉执行; 2.维护共享变量在多个线程之间的可见性; public class demo { private boolean ready=false; private int result=0; private int number=1; public synchronized void write(){
指令重排序优化分析和volatile对编译优化的作用
转自 http://heavensay.iteye.com/blog/1455349 <em>指令</em><em>重排序</em>       <em>指令</em><em>重排序</em>的原因:对主存的一次访问一般花费硬件的数百次时钟周期。处理器通过缓存(寄存器、cpu缓存等)能够从数量级上降低内存延迟的成本这些缓存为了性能重新排列待定内存操作的顺序。也就是说,程序的读写操作不一定会按照它要求处理器的顺序执行。 一、编译期<em>重排序</em> 编译期<em>重排序</em>的典
Java内存结构
Java内存结构: 深入理解Java内存模型一基础并发编程模型的分类Java内存模型的抽象<em>重排序</em>处理器<em>重排序</em>与内存屏障<em>指令</em>happens-before深入理解Java内存模型二<em>重排序</em>数据依赖性..
三、Java内存模型---重排序和顺序一致性
3.2 <em>重排序</em> <em>重排序</em>是指编译器和处理器为了优化程序性能而对<em>指令</em>序列进行重新排序的一种手段。 3.2.1 数据依赖性 如果两个操作访问同一个变量,且这两个操作中有一个为写操作,此时这两个操作之间 就存在数据依赖性。数据依赖分为下列3种类型,如表3-4所示。 上面3种情况,只要<em>重排序</em>两个操作的执行顺序,程序的执行结果就会被改变。 前面提到过,编译器和处理器可能会对操作做<em>重排序</em>。编译
处理器重排序与内存屏障
处理器<em>重排序</em>: 现代处理器使用写缓冲区来临时保存向内存写数据。 内存屏障<em>指令</em> 为了保证内存可见性,<em>java</em>编译器在生成编译器<em>指令</em>时,会假如内存屏障<em>指令</em>来禁止特定的处理器<em>重排序</em>
指令重排的原因以及可能造成的问题
为何要<em>指令</em>重排?        现在的CPU一般采用流水线来执行<em>指令</em>。一个<em>指令</em>的执行被分成:取指、译码、访存、执行、写回、等若干个阶段。然后,多条<em>指令</em>可以同时存在于流水线中,同时被执行。 <em>指令</em>流水线并不是串行的,并不会因为一个耗时很长的<em>指令</em>在“执行”阶段呆很长时间,而导致后续的<em>指令</em>都卡在“执行”之前的阶段上。 相反,流水线是并行的,多个<em>指令</em>可以同时处于同一个阶段,只要CPU内部相应的处理
深入分析Synchronized原理
深入分析Synchronized原理 Java高级架构师 2018-08-16 17:16:45 0 前言 记得开始学习Java的时候,一遇到多线程情况就使用synchronized,相对于当时的我们来说synchronized是这么的神奇而又强大,那个时候我们赋予它一个名字“同步”,也成为了我们解决多线程情况的百试不爽的良药。但是,随着学习的进行我们知道在JDK1.5之前synchroni...
Java并发编程 之 指令重排序
<em>指令</em><em>重排序</em> <em>重排序</em>的目的是提高运行并发度,发生在编译器和处理器阶段,遵循as-if-serial语义(不管怎么<em>重排序</em>,单线程程序的执行结果不能改变),也就是<em>重排序</em>所带来的<em>问题</em>是针对多线程的。 <em>重排序</em>发生的条件是A和B没有存在依赖关系,这里的依赖关系是指数据依赖关系和控制依赖关系两种。其中数据依赖表示两个以上操作访问同一个变量,且这两个操作中有一个为写操作。而控制依赖关系,比如if(a>0){in
JAVA内存模型--指令重排序
<em>指令</em><em>重排序</em> 在执行程序时,为了提高性能,编译器和处理器会对<em>指令</em>做<em>重排序</em>。但是,JMM确保在不同的编译器和不同的处理器平台之上,通过插入特定类型的Memory Barrier来禁止特定类型的编译器<em>重排序</em>和处理器<em>重排序</em>,为上层提供一致的内存可见性保证。 编译器优化<em>重排序</em>:编译器在不改变单线程程序语义的前提下,可以重新安排语句的执行顺序。 <em>指令</em>级并行的<em>重排序</em>:现代处理器采用了<em>指令</em>级并行技术(Ins...
Java指令重排序
在执行程序时候,为了提高性能,编译器和处理器常常会对<em>指令</em>做<em>重排序</em>。<em>重排序</em>分3中类型。 1、编译器优化的<em>重排序</em>。编译器在不改变单线程程序语义的前提下,可以重新安排语句的执行顺序。 2、<em>指令</em>级并行的<em>重排序</em>。现代处理器采用了<em>指令</em>级并行技术来将多条<em>指令</em>重叠执行。如果不存在数据的依赖性,处理器可以改变语句对应机器<em>指令</em>的执行顺序。 3、内存系统的<em>重排序</em>。由于处理器使用缓存和读/写缓冲区,这使得加载和存储
什么是指令重排序
什么是<em>指令</em><em>重排序</em>? 有两个层面: **在虚拟机层面,**为了尽可能减少内存操作速度远慢于CPU运行速度所带来的CPU空置的影响,虚拟机会按照自己的一些规则(这规则后面再叙述)将程序编写顺序打乱——即写在后面的代码在时间顺序上可能会先执行,而写在前面的代码会后执行——以尽可能充分地利用CPU。拿上面的例子来说:假如不是a=1的操作,而是a=new byte1024*1024,那么它会运行地很慢,此时...
JMM——重排序与happens-before
数据依赖性 如果两个操作访问同一个变量,且这两个操作中有一个为写操作,此时这两个操作之间就存在数据依赖性。数据依赖分为下列三种类型:   上述三种情况,只要<em>重排序</em>两个操作的执行顺序,程序的执行结果将会被改变 只有编译器和处理器在<em>重排序</em>时会遵守数据依赖性,它们不会改变存在数据依赖性关系的两个操作的执行顺序。 但是不同处理器之间和不同线程之间的数据依赖性不被编译器和处理器考虑   a
volatitle深入解析
今天来介绍一下volatitle volatile是什么 volatitle是一个确保共享变量能够被准确和一致地更新的关键字(保证可见性),只能对变量使用 volatile是如何保证可见性的 在对有volatile修饰符修饰的共享变量进行写操作时,汇编代码回多一条lock前缀的<em>指令</em>。该<em>指令</em>有如下两个作用: 将当前缓存行的数据回写到内存中 使其他cpu里缓存了该内存地址的数据无效...
为什么要指令重排序
我们知道<em>java</em>在运行的时候有两个地方可能用到<em>重排序</em>,一个是编译器编译的的时候,一个是处理器运行的时候。 那么我们就应该问问为啥要用<em>指令</em><em>重排序</em>呢? 生活类比 我们从生活中举个例子,假设你有一箱红纸,现在要你剪成小红花贴在窗上。你有两种极端的选择:拿出来一个,把这个剪好,再贴上去......一个一个依次进行;另一种方式是先全部拿出来,然后全部剪好,最后全部贴上去。 那种效率更高?很明显是后者,因为前...
由一个单例模式引发的对指令重排的思考
先说下单例模式,由于频繁创建对象比较浪费资源,就考虑将所有用到某个类的实例时,公用同一个实例,于是就有了单例模式。 单例模式写法有很多,于是我看到了这么一种写法: public class SingletonTest { private SingletonTest() { } private static SingletonTest singletonT...
记一次你不知道到单例模式之重排序
其实工作中单例模式也是很常见的,也有很多种写法,今天在这里也只说一种方式,也是面试中遇到的,请先看一下两种双重检查锁的写法有什么不同(以下内容引自《<em>java</em>并发编程的艺术》一书)。 (1) public class DoubleCheckedLocking { private static DoubleCheckedLocking doubleCheckedLocking ; ...
双重检查锁定(double-checked locking)与单例模式
单例模式有如下实现方式:package com.zzj.pattern.singleton; public class Singleton { private static Singleton instance; private Singleton() { } public static Singleton getInstance() { if (instance == null
Java 内存模型(三)-从源代码到指令序列的重排序
在执行程序时。为了提高性能,编译器和处理器常常会对<em>指令</em>做<em>重排序</em>。<em>重排序</em>分为3中类型: 1 编译器优化的<em>重排序</em>。编译器在不改变单线程程序语义的前提下,可以重新安排语句的执行顺序。 2 <em>指令</em>级并行的<em>重排序</em>。现代处理器采用了<em>指令</em>集并行技术(ILP) ,来讲多条<em>指令</em>重叠执行。如果不存在数据依赖性,处理器可以改变语句对机器<em>指令</em>的执行顺序。 3 内存系统的<em>重排序</em>。由于处理器使用缓存和读/写缓冲区。这便得...
JMM 指令重排
<em>指令</em>重排 对于编译器的编写者来说,Java内存模型(JMM)主要是由禁止<em>指令</em>重排的规则所组成的,其中包括了字段(包括数组中的元素)的存取<em>指令</em>和监视器(锁)的控制<em>指令</em>。 Volatile与监视器 JMM中关于volatile和监视器主要的规则可以被看作一个矩阵。这个矩阵的单元格表示在一些特定的后续关联<em>指令</em>的情况下,<em>指令</em>不能被重排。下面的表格并不是JMM规范包含的,而是一个用来观察J
volatile 指令重排序问题
[code=<em>java</em>]package org.volatiles;rnrnimport <em>java</em>.io.IOException;rnimport <em>java</em>.util.Properties;rnrn/**rn * volatile禁止<em>指令</em><em>重排序</em>优化rn * rn * @author Byronrn * rn */rnpublic class VolatileTest2 rnrn boolean initialized = false;rn String name;rn String age;rn String sex;rnrn public static void main(String[] args) rn VolatileTest2 test = new VolatileTest2();rn test.start();rn rnrn public void start() rn Thread t1 = new Thread(new GetProperties());rn Thread t2 = new Thread(new UseProperties());rn t1.start();rn t2.start();rnrn rn /**rn * 获取文件中的属性信息rn * @author Byronrn *rn */rn class GetProperties implements Runnable rn @Overridern public void run() rn Properties p = new Properties();rn try rn p.load(getClass().getResourceAsStream("test.properties"));rn name = p.getProperty("name");rn age = p.getProperty("age");rn sex = p.getProperty("sex");rn initialized = true;// 实验了无数次还是没有出现<em>重排序</em>rnrn catch (IOException e) rn e.printStackTrace();rn rn rn rn /**rn * 读取GetProperties从文件中取出的信息rn * @author Byronrn *rn */rn class UseProperties implements Runnable rn @Overridern public void run() rn while (!initialized) rn // waitrn // System.out.println("wait 1 ms");rn rn System.out.println("name is: " + name);rn System.out.println("age is: " + age);rn System.out.println("sex is: " + sex);rn rn rnrnrn[/code]rn始终没有出现<em>指令</em><em>重排序</em>,为什么?
java并发DCL问题
<em>java</em>并发之单例模式,在早期的jvm中,synchronized存在巨大的性能开销。如果getInstance的竞争很小,甚至没有竞争,那么synchronized就存在很大的冗余性能开销。所以通过双重检查机制避免不必要的锁操作。
Java中的volatile关键字详解及单例模式双检锁问题分析
【参考文献】http://www.cnblogs.com/dolphin0520/p/3920373.html 看了好多关于volatile关键字的文章,这篇应该是讲得最清楚的了吧,从Java内存模型出发,结合并发编程中的原子性、可见性、有序性三个角度分析了volatile所起的作用,并从汇编角度大致说了volatile的原理,说明了该关键字的应用场景;我在这补充一点,分析下volatile是怎
技术分享-JAVA并发库解读
<em>重排序</em>:为优化程序性能,编译器和处理器对<em>指令</em>重新排序。
java内存模型,happens-before与指令重排序
最近在学习<em>java</em>并发方面的知识,关于“happens-before”与“<em>重排序</em>”有些疑问。rn资料1:http://blog.csdn.net/zhushuai1221/article/details/51491578 这篇文章里提到:volatile会禁止CPU对<em>指令</em>进行<em>重排序</em>rn资料2:http://ifeve.com/easy-happens-before/rn资料3:http://www.w2bc.com/article/110564 这篇文章倒数第二段有个结论:因此,“一个操作happen—before另一个操作”并不代表“一个操作时间上先发生于另一个操作”。rn看例子:rn[code=<em>java</em>]class Example rn int a = 0; rn CopyOnWriteArrayList list = new CopyOnWriteArrayList(); rn rn //in thread A rn public void writer() rn a = 1; //p1操作rn list.set(0,"t"); //p2操作rn rn rn //in thread B rn public void reader() rn list.get(0); //p3操作rn int b = a; //p4操作rn rn [/code]rn可能的执行时序1:rn[code=text]线程A 线程Brn p1:a = 1 rn p2:list.set(0,"t") rn p3:list.get(0)rn p4:int b = a;[/code]可能的执行时序2:rn[code=text]线程A 线程Brn p1:a = 1 rn p3:list.get(2)rn p2:list.set(1,"t") rn p4:int b = a;[/code]rn在“可能的执行时序1”中,p1,p2是同一个线程中的,p3,p4是同一个线程中的,所以有hb(p1,p2),hb(p3,p4)(p1 happens-before p2,p3 happens-before p4);由于CopyOnWriteArrayList能保证set操作happens-before(hb) get操作,且hb关系具有传递性,所以hb(p1,p4) 因此可以保证线程2中的b的值是1。rnrn我的疑问:rn疑问1:单线程情况下,由于p1与p2操作并不存在数据依赖与逻辑依赖,并且list内部的volatile变量“看不见”Example类的a变量(相关知识见资料1),因此p1与p2单线程下可能会发生<em>重排序</em>导致先执行p2再执行p1。这个分析是正确的吗?rn疑问2:什么情况下某个a操作后执行于某个b操作却能保证“a happens-before b”?请重新举个例子,因为资料3里的说的看不太明白。或者说:rn【在A、B线程同时执行的情况下,由于存在关系hb(p1,p2),hb(p3,p4),只要hb(p2,p3)成立(此时hb(p1,p4)成立), 那么p1与p2(或p3与p4)肯定不会发生<em>重排序</em>,否则hb(p1,p4)就不成立了(难道真的存在 p2时间上比p1先执行却还能保证hb(p1,p2)成立?想不明白);只要hb(p2,p3)不成立,p1与p2(或p3与p4)随便<em>重排序</em>,反正也不影响程序的执行结果?】rnrn有点乱,求大神指教。。
java多线程之指令重排序
<em>重排序</em>  在执行程序时,为了提高性能,编译器和处理器常常会对<em>指令</em>做<em>重排序</em>。<em>重排序</em>分3种类型。 1)编译器优化的<em>重排序</em>。编译器在不改变单线程程序语义的前提下,可以重新安排语句的执行顺序。 2)<em>指令</em>级并行的<em>重排序</em>。现代处理器采用了<em>指令</em>级并行技术(Instruction-Level Parallelism,ILP)来将多条<em>指令</em>重叠执行。如果不存在数据依赖性,处理器可以改变语句对应机器<em>指令</em>的执行
windows builder pro for eclipse 3.7 天涯浪子下载
一款基于Eclipse SWT技术上的双向Java Gui设计软件。具备SWT设计以及Swing设计两个主要功能。该软件会被作为一个插件镶嵌入Eclipse以及其他一些兼容的IDEs中 note:WindowBuilder Pro is a market-leading GUI builder that includes SWT Designer, Swing Designer and GWT Designer and enables user interfaces to be created in minutes with tools for intelligent layout assis 相关下载链接:[url=//download.csdn.net/download/sbfivwsll/3516326?utm_source=bbsseo]//download.csdn.net/download/sbfivwsll/3516326?utm_source=bbsseo[/url]
北京理工大学计算机专业研究生复试上机试题(2000-2008)下载
北京理工大学计算机专业研究生复试上机试题(2000-2008) 相关下载链接:[url=//download.csdn.net/download/ningfuxuan/2023115?utm_source=bbsseo]//download.csdn.net/download/ningfuxuan/2023115?utm_source=bbsseo[/url]
实用公文写作指导大全下载
本书是对我国机关、事业好企业单位几十种常用公文书写格式和书写方法的总结,对相关人员进行公文写作具有指导作用。 相关下载链接:[url=//download.csdn.net/download/yangyx_cau/2105879?utm_source=bbsseo]//download.csdn.net/download/yangyx_cau/2105879?utm_source=bbsseo[/url]
文章热词 设计制作学习 机器学习教程 Objective-C培训 交互设计视频教程 颜色模型
相关热词 mysql关联查询两次本表 native底部 react extjs glyph 图标 学习java问题 学习java的问题
我们是很有底线的