首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

Java内存模型与指令重排

本文暂不讲JMM(Java Memory Model)中的主存, 工作内存以及数据如何在其中流转等等, 这些本身还牵扯到硬件内存架构, 直接上手容易绕晕, 先从以下几个点探索JMM 原子性 有序性 可见性...指令重排 CPU指令重排 编译器优化重排 Happen-Before规则 原子性 原子性是指一个操作是不可中断的....编译器优化 主要是Java虚拟机层面的可见性, 下文会有详细讲述. 指令重排 指令重排是指在程序执行过程中, 为了性能考虑, 编译器和CPU可能会对指令重新排序....指令重排只可能发生在毫无关系的指令之间, 如果指令之间存在依赖关系, 则不会重排. 如 指令1 : a = 1 指令2: b = a - 1, 则指令1, 2 不会发生重排....再来看两个从Java语言规范中摘取的例子, 也是涉及到编译器优化重排, 这里不再做详细解释, 只说下结果. 例子1中有可能出现r2 = 2 并且 r1 = 1; ?

1.7K50
您找到你想要的搜索结果了吗?
是的
没有找到

Java发生指令重排的几个地方

一.指定重排的原则 编译器和处理器不是胡乱的重排序的,他们会遵循一个关键的规则,就是数据依赖规则,如果说一个变量的结果依赖于之前的代码执行结果,那么就不能随意进行重排序,要遵循数据的依赖。...二.指定重排的位置 2.1 编译时 编译后的代码的执行顺序:java里有两种编译器,一个是静态编译器(javac),一个是动态编译器(JIT)。...javac负责把.java文件中的源代码编译为.cass文件中的字节码,这个一般是程序写好之后进行编译的。...2.2 处理器执行时候 即使我们给处理器一个代码的执行顺序,处理器也可能会重排代码,更换一种执行顺序。...2.3 内存重排序 有可能一个处理器在实际执行的过程中,在写缓冲器,高速缓存等等一些硬件也能导致指令执行顺序和我们想象的不一样。 如图所示,画红圈的都是可能发生指定重排的地方

68840

Java 并发编程】线程指令重排序问题 ( 指令重排序规范 | volatile 关键字禁止指令重排序 )

文章目录 总结 一、指令重排序规范 二、指令重排序示例 总结 Java 并发的 3 特性 : 原子性 : 每个操作都是 不可拆分的原子操作 ; 在线程中进行 a++ 就不是原子操作 , 该操作分为..." ; 保证 有序性 ; 一、指令重排序规范 ---- 指令重排指的是 , 线程中如果两行代码 没有逻辑上的上下关系 , 可以对代码进行 重新排序 ; JVM 指令重排遵循规范 : as-if-serial...规范 : 单个线程中, 指令的重排 , 不能影响程序的执行结果 ; 可以重排的情况 : 对于下面代码 , 两条指令顺序颠倒 , 执行结果相同 , 可以进行指令重排 ; x = 0; y = 1; 不可以进行重排的情况...: 对于下面的代码 , 两条指令如果上下颠倒 , 结果不同 , 不可以进行指令重排 ; x = 0; y = x; happens-before 规范 : 先行发生原则 ; 二、指令重排序示例 ---...协同式调度 : 线程执行时间 由 线程 决定 ; 抢占式调度 : 线程执行事件 由 系统 决定 ; 上述示例中的线程调度方式是 " 抢占式调度 " , 谁先执行 由系统分配 , 这两个线程的执行顺序都是随机

74520

从源代码到Runtime发生的重排序编译器重排序指令重排序内存系统重排序阻止重排

然而改变顺序执行很危险,很有可能使得运行结果和预想的不一样,特别是当重排序共享变量时。  从源代码到Runtime需要经过三步的重排序: ?...编译器重排序  为了提高性能,在不改变单线程的执行结果下,可以改变语句执行顺序。  比如尽可能的减少寄存器的读写次数,充分利用局部性。... 指令重排序是处理器层面做的优化。...阻止重排序  不论哪种重排序都可能造成共享变量中线程间不可见,这会改变程序运行结果。所以需要禁止对那些要求可见的共享变量重排序。 阻止编译重排序:禁止编译器在某些时候重排序。...阻止指令重排序和内存系统重排序:使用内存屏障或Lock前缀指令

1.4K90

java 唯一随机数_JAVA随机

⑤UUID类 静态方法:static UUID randomUUID():获取类型 4(伪随机生成的)UUID 的静态工厂。 使用加密的强伪随机数生成器生成该 UUID。...(Math.random()*(max-min)+min); ②Random类 使用java.util.Random类来产生一个随机数发生器,这个也是我们在j2me的程序里经常用的一个取随机数的方法。...+1) + min; ③ThreadLocalRandom 在多线程下,使用 java.util.Random 产生的实例来产生随机数是线程安全的,但深挖 Random 的实现过程,会发现多个线程会竞争同一...多线程下获取[1,100)的随机数,如下代码 import java.util.concurrent.ThreadLocalRandom; public class ThreadLocalRandomDemo...,还可以将其对某些数取模,就能限制随机数的范围;此方式在循环中同时产生多个随机数时,会是相同的值,有一定的局限性!

3K20

【死磕Java并发】-----Java内存模型之重排

其实JVM对异常做了一种特殊的处理,为了保证as-if-serial语义,Java异常处理机制对重排序做了一种特殊的处理:JIT在重排序时会在catch语句中插入错误代偿代码(a = 3),这样做虽然会导致...重排序对多线程的影响 在单线程环境下由于as-if-serial语义,重排序无法影响最终的结果,但是对于多线程环境呢?...假如操作1 和操作2 之间重排序: ? 按照这种执行顺序线程B肯定读不到线程A设置的a值,在这里多线程的语义就已经被重排序破坏了。 操作3 和操作4 之间也可以重排序,这里就不阐述了。...假如操作3 和操作4重排序了,操作4 先执行,则先会把计算结果临时保存到重排序缓冲中,当操作3 为真时才会将计算结果写入变量i中 通过上面的分析,重排序不会影响单线程环境的执行结果,但是会破坏多线程的执行语义...参考资料 周志明 :《深入理解Java虚拟机》 方腾飞:《Java并发编程的艺术》 END

47720

【死磕Java并发】—– Java内存模型之重排

在执行程序时,为了提供性能,处理器和编译器常常会对指令进行重排序,但是不能随意重排序,不是你想怎么排序就怎么排序,它需要满足以下两个条件: 在单线程环境下不能改变程序运行的结果; 存在数据依赖关系的不允许重排序...其实JVM对异常做了一种特殊的处理,为了保证as-if-serial语义,Java异常处理机制对重排序做了一种特殊的处理:JIT在重排序时会在catch语句中插入错误代偿代码(a = 3),这样做虽然会导致...重排序对多线程的影响 在单线程环境下由于as-if-serial语义,重排序无法影响最终的结果,但是对于多线程环境呢?...假如操作1 和操作2 之间重排序: ? 按照这种执行顺序线程B肯定读不到线程A设置的a值,在这里多线程的语义就已经被重排序破坏了。 操作3 和操作4 之间也可以重排序,这里就不阐述了。...参考资料 周志明 :《深入理解Java虚拟机》 方腾飞:《Java并发编程的艺术》

70170

【死磕Java并发】—–Java内存模型之重排

在执行程序时,为了提供性能,处理器和编译器常常会对指令进行重排序,但是不能随意重排序,不是你想怎么排序就怎么排序,它需要满足以下两个条件: 在单线程环境下不能改变程序运行的结果; 存在数据依赖关系的不允许重排序...其实JVM对异常做了一种特殊的处理,为了保证as-if-serial语义,Java异常处理机制对重排序做了一种特殊的处理:JIT在重排序时会在catch语句中插入错误代偿代码(a = 3),这样做虽然会导致...重排序对多线程的影响 在单线程环境下由于as-if-serial语义,重排序无法影响最终的结果,但是对于多线程环境呢?...假如操作1 和操作2 之间重排序: ? 按照这种执行顺序线程B肯定读不到线程A设置的a值,在这里多线程的语义就已经被重排序破坏了。 操作3 和操作4 之间也可以重排序,这里就不阐述了。...参考资料 周志明 :《深入理解Java虚拟机》 方腾飞:《Java并发编程的艺术》

51960

Java】单例模式及指令重排问题

单例模式介绍 在Java中单例设计模式准确来说是,类的单例设计模式,就是采取一定的方法保证在整个的软件系统中,对某个类只能存在一个对象实例,并且该类只提供一个取得其对象实例的方法。 2....null) { single = new Singleton(); } return single; } } 同步代码块解决(推荐):指令重排问题解决...private static volatile Singleton single;//声明为volatile解决指令重排 // 3.提供公共的静态的方法,返回当前类的对象。...} } return single; } } } /* 注意:上述方式2中,有指令重排问题 mem = allocate(); 为单例对象分配内存空间...但是需要 volatile关键字,避免指令重排(在成员属性上声明)。 */ 6.

53040

Java并发编程的艺术(二)——重排

什么是重排序? 重排序指的是编译器、处理器在不改变程序执行结果的前提下,重新排列指令的执行顺序,以达到最佳的运行效率。 重排序分类 重排序分为:编译器重排序 和 处理器重排序。...因此,编译器和处理器只会对没有依赖关系的指令进行重排序。 数据依赖:若相邻的两条指令访问同一个变量,并且其中有一条指令执行写操作,那么这样的两条指令之间存在数据依赖。...对于有数据依赖关系的指令,不会发生重排序。...数据依赖关系总结一下为以下三种情况: 指令 示例 读后写 a=b;b=1; 写后写 a=1;a=2; 写后读 a=1;b=a; as-if-serial 在单线程开发中,程序员不需要知道指令是如何重排序的

727100

Java里认识汇编指令重排

这些重排方式都可以提高程序的性能和效率,但同时也需要注意保证程序的正确性。编译器和处理器在进行重排时,需要遵守程序的语义规则,确保程序在重排后的执行结果与原始程序相同。...一、对象创建过程 对象创建过程,指令不只是一条,所以多线程执行会进行重排序,如图所示: 可以用编译直接打开java对象编译后的class文件,就可以看到,new对象生成的指令不止一个。...二、Java代码验证指令重排 单线程环境里面确保程序最终执行结果和代码顺序执行的结果一致的。...三、禁止指令重排Java中,可以通过将变量声明为`volatile`或使用`synchronized`关键字来禁止指令重排。 1....例如: synchronized(this){ // 执行需要禁止重排的代码 } 总结 从Java的角度看汇编语言的指令重排序,我们可以理解到这是一种提高程序执行效率的技术,但在多线程环境中需要谨慎处理

29770

进制重排

undefined 二进制重排这个方案最早也是 抖音团队 分享的。 三、二进制重排 1....二进制重排操作 苹果已经给我们提供了这个机制,实际上 二进制重排就是对即将生成的可执行文件重新排列,这个操作发生在链接阶段。...2.3 二进制重排原理 我们二进制重排并非只是修改符号地址,而是利用符号顺序,重新排列整个代码在文件的偏移地址,将启动需要加载的方法地址放到前面内存页中,以此达到减少`page fault`的次数从而实现时间上的优化...xxx.order文件来实现二进制重排,获取的方案使用 Clang编译插桩。...,对比前后xxx-LinkMap-normal-arm64.txt文件,我们会发现启动时调用的方法,已经被排到前边去了 二进制重排前 二进制重排后 四、使用 System Trace 来检验二进制重排结果

60920

java uuid 随机数_Java随机数和UUID

Java随机数和UUID# Java随机数 在Java项目中通常是通过Math.random方法和Random类来获得随机数,前者通过生成一个Random类的实例来实现。...此类产生的是一组伪随机数流,通过使用 48 位的种子,利用线性同余公式产生。在Java中,随机数的产生取决于种子,随机数和种子之间的关系遵从以下两个规则: 种子不同,产生不同的随机数。...Java UUID UUID(Universally Unique Identifier)全局唯一标识符,是指在一台机器上生成的数字,它保证对在同一时空中的所有机器都是唯一的。...如果应用只是在局域网中使用,也可以使用退化的算法,以IP地址来代替MAC地址--Java的UUID往往是这样实现的(当然也考虑了获取MAC的难度)。...UUID Version 4:随机UUID 根据随机数,或者伪随机数生成UUID。

2.8K30

扫码

添加站长 进交流群

领取专属 10元无门槛券

手把手带您无忧上云

扫码加入开发者社群

相关资讯

热门标签

活动推荐

    运营活动

    活动名称
    广告关闭
    领券