[JMM]__JMM中的普通final域重排序规则

关于final域,编译器和处理器遵循2个重排序规则:

1,在构造函数内部,对final域的成员变量的写入,与随后将这个被构造的对象赋值给另一个引用变量,这2个操作不能重排序

2,初次读一个包含final域的对象的引用,与随后读这个final域,这2个操作之间不能重排序.

上面的重排序规则能保证,在对象的引用在被任何线程可见之前,该对象中的final域已经被正确初始化了.而普通域

不具有这个保障.

即,在对象引用被其他线程可见时,该对象可能还未构造完成,即其中的普通域由于被重排序到构造函数之外,此时普通域变量还未被写入.初始值.

如下图,一个普通域被重排序到构造函数外:

时间: 2024-10-09 23:36:13

[JMM]__JMM中的普通final域重排序规则的相关文章

[JMM]__JMM中引用类型final域重排序规则

对于final域为引用类型的情况: 1,在构造函数内,对于一个final域为引用类型及对其引用的对象的成员变量的写入,与随后在构造函数外将被构造的对象赋值给另一引用变量,这2个操作不能被重排序. 如下图详解:

无法解决 equal to 运算中 "Chinese_PRC_90_CI_AS" 和 "Chinese_PRC_BIN" 之间的排序规则冲突

这是因为数据库 oa 和 hh 的编码格式不一样导致的 select  groupname as oper_id,name as oper_name from security_users where name collate Chinese_PRC_CI_AS not in (select oper_name from PDA_UsersAndPWD )

Java并发编程之final域的内存语义

一.final域的重排序规则 对于final域,编译器和处理器要遵循两个重拍序规则: 1.在构造函数内对一个final域的写入,与随后把这个被构造对象的引用赋值给一个引用变量,这两个操作之间不能重排序. 2.初次读一个包含final域的对象的应用,与随后初次读这个final域,这两个操作之间不能重排序 下面通过一个示例来分别说明这两个规则: public class FinalTest { int i;//普通变量 final int j; static FinalTest obj; publi

Java并发编程原理与实战四十四:final域的内存语义

一.final域的重排序规则 对于final域,编译器和处理器要遵循两个重拍序规则: 1.在构造函数内对一个final域的写入,与随后把这个被构造对象的引用赋值给一个引用变量,这两个操作之间不能重排序. 2.初次读一个包含final域的对象的应用,与随后初次读这个final域,这两个操作之间不能重排序 下面通过一个示例来分别说明这两个规则: public class FinalTest { int i;//普通变量 final int j; static FinalTest obj; publi

Java内存模型-final域的内存语义

一 引言 说到final你肯定知道它是Java中的关键字,那么它所在Java中的作用你知道吗?不知道的话,请前往这篇了解下https://www.cnblogs.com/yuanfy008/p/8021673.html 今天我们来说说final域在JMM中的内存语义. 二 final域的重排序规则 开门见山,对于final域,编译器和处理器一定要遵守两个重排序规则(JSR-133才增强了final域): 1)在构造函数内对一个final域的写入,与随后把这个被构造对象的引用赋值给一个引用变量,这

Java并发拾遗(一)——并发、JMM与重排序

一.并发中的关键问题及其解决思路 并发中的关键问题:1. 线程之间如何通信 -- 线程之间如何交换信息2. 线程之间如何同步 -- 控制线程的相对执行顺序 两种解决思路: 1. 隐式通信,显示同步 -- 线程之间通过共享内存中的公共状态来隐式通信,那么就必须显示的指定线程见的互斥来实现同步2. 显式通信,隐式同步 -- 线程之间无公共状态,通过明确的发送消息进行通信,那么由于消息的发送在消息接收之前,就可以实现隐式的同步 Java选择了共享内存的方式来解决并发中的两个关键问题,因此Java中线程

深入理解JMM(Java内存模型) --(二)重排序

[转载自并发编程网 – ifeve.com 原文链接:http://ifeve.com/tag/jmm/] 数据依赖性 如果两个操作访问同一个变量,且这两个操作中有一个为写操作,此时这两个操作之间就存在数据依赖性.数据依赖分下列三种类型: 名称 代码示例 说明 写后读 a = 1;b = a; 写一个变量之后,再读这个位置. 写后写 a = 1;a = 2; 写一个变量之后,再写这个变量. 读后写 a = b;b = 1; 读一个变量之后,再写这个变量. 上面三种情况,只要重排序两个操作的执行顺

Java并发编程原理与实战四十一:重排序 和 happens-before

一.概念理解 首先我们先来了解一下什么是重排序:重排序是指编译器和处理器为了优化程序性能而对指令序列进行重新排序的一种手段. 从Java源代码到最终实际执行的指令序列,会分别经历下面3种重排序,如下图所示 上述的1属于编译器重排序,2和3属于处理器重排序.这些重排序可能会导致多线程程序出现内存可见性问题.在单线程程序中,对存在控制依赖的操作重排序,不会改变执行结果(这也是as-if-serial语义允许对存在控制依赖的操作做重排序的原因):但在多线程程序中,对存在控制依赖的操作重排序,可能会改变

深入理解Java内存模型(二)——重排序

数据依赖性 如果两个操作访问同一个变量,且这两个操作中有一个为写操作,此时这两个操作之间就存在数据依赖性.数据依赖分下列三种类型: 名称 代码示例 说明 写后读 a = 1;b = a; 写一个变量之后,再读这个位置. 写后写 a = 1;a = 2; 写一个变量之后,再写这个变量. 读后写 a = b;b = 1; 读一个变量之后,再写这个变量. 上面三种情况,只要重排序两个操作的执行顺序,程序的执行结果将会被改变. 前面提到过,编译器和处理器可能会对操作做重排序.编译器和处理器在重排序时,会