首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Java中的双重检查锁定和代码重新排序

Java中的双重检查锁定和代码重新排序
EN

Stack Overflow用户
提问于 2013-08-06 03:05:56
回答 3查看 525关注 0票数 0

在一篇文章中,我读到双止回阀锁坏了。因为编译器可以重新排序构造函数的顺序。

  1. Ss为对象分配内存。
  2. 然后将地址返回给引用变量。
  3. 然后初始化对象的状态。

虽然人们通常会期望:

  1. 它应该作为为对象分配的内存。
  2. 然后初始化对象的状态。
  3. 然后将地址返回给引用变量。

同样,在使用synchronized关键字时,代码重新排序永远不会按照JMM规范进行。

为什么编译器在同步()块中重新排序构造函数事件的顺序?

我在这里看到了很多关于DCL的文章,但我期待基于JMM和编译器重新排序的描述。

EN

回答 3

Stack Overflow用户

发布于 2013-08-06 03:42:27

编译器可以在同步块中重新排序指令。编译器可以在同步块之前(只要它们在前面)或之后(只要它们在后面)重新排序。但是,编译器不能自由地跨同步块边界(块开始或块结束)重新排序指令。

因此,完全在同步块内的构造和分配可以重新排序,没有正确同步的外部查看器可以在构造之前看到分配。

票数 3
EN

Stack Overflow用户

发布于 2013-08-06 04:32:22

为什么编译器在同步()块中重新排序构造函数事件的顺序?

它通常会这样做,以使代码运行得更快。

Java语言规范(JLS)指出,实现(例如编译器)可以在某些约束条件下重新排序指令和指令序列。

问题是,DCL的坏变体所作的假设超出了JLS所说的范围。其结果是执行JLS认为格式不太好。这是否显示为实际的错误/意外行为取决于编译器版本、硬件和其他各种事情。

但关键是编译器没有做错任何事情。错误在DCL代码中。

我只想补充一下,JIT编译器通常不会重新排序事件本身。它经常做的是消除硬件级内存读/写操作的限制。例如,通过删除特定内存写入被刷新到主存的约束,允许硬件延迟(甚至完全跳过)缓慢写入内存,只需将其写入L1缓存即可。相反,synchronized块的结束将强制对主内存进行缓存的写操作,产生额外的内存流量,(可能)一个管道停止。

票数 0
EN

Stack Overflow用户

发布于 2013-08-06 07:08:26

首先:

再次使用关键字时,代码重新排序永远不会按照JMM规范进行。

上述说法不完全准确。JMM定义了发生之前的关系。JLS只定义程序顺序并在顺序之前发生。见http://docs.oracle.com/javase/specs/jls/se7/html/jls-17.html#jls-17.4.5

它对指令的重新排序有影响。例如,

代码语言:javascript
复制
int x = 1;
synch(obj) {
    y = 2;
}
int z = 3;

现在,对于上面的代码,以下类型的重新排序是可能的。

代码语言:javascript
复制
synch(obj) {
    int x = 1;
    y = 2;
    int z = 3;
}

以上是一个有效的重新排序。

http://jeremymanson.blogspot.in/2007/05/roach-motels-and-java-memory-model.html

代码语言:javascript
复制
synch(obj) {
    int z = 3;
    y = 2;
    int x = 1;
}

以上也是一个有效的重新排序。

不可能的是,只有在获得锁之后,在释放锁之前才能执行y=2,这是JMM所保证的。另外,要查看来自另一个线程的正确效果,我们只需要在同步块中访问y。

现在我来到DCL。

请参阅DCL的代码。

代码语言:javascript
复制
if (singleton == null)
    synch(obj) {
        if(singleton == null) {
            singleton == new Singleton()
        }
    }
return singleton;

现在,上述方法的问题是:

  1. singleton = new Singleton()不是一条指令。但是一套指令。在完全初始化构造函数之前,很可能先为单个引用分配对象引用。
  2. 因此,如果发生1,则其他线程很可能将单个引用读取为非null,从而看到部分构造的对象。

上述影响可以控制,使一个单一的人,因为不稳定,这也确定发生-之前的保证和能见度。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/18071190

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档