【问题标题】:The reorder explanation of modified String.hashCode()修改后的 String.hashCode() 的重新排序说明
【发布时间】:2013-05-29 11:10:24
【问题描述】:

请参阅此blog 和此topic

似乎即使在单线程中代码也会重新排序?

public int hashCode() {
 if (hash == 0) { // (1)
     int off = offset;
     char val[] = value;
     int len = count;

     int h = 0;
     for (int i = 0; i < len; i++) {
         h = 31*h + val[off++];
     }
     hash = h;
  }
  return hash; // (2)
}

但这真的让我很困惑,为什么 (2) 可以返回 0 而 (1) 可以是非零?

如果我在单线程中使用代码,这甚至不起作用,怎么会发生?

【问题讨论】:

  • 这只是一个多线程问题。
  • 他@MarkoTopolnik,如何在多线程中执行重新排序?我不确定,但我认为 reordering 是在字节码中执行的,与线程无关?
  • 重新排序绝对不会发生在字节码级别;这是一个与 JIT 编译器相关的问题。保证您在单个线程内有理智的行为。
  • @MarkoTopolnik,但是为​​什么 reordering 的行为在多线程和单线程之间是不同的?
  • @MrROY:这已经偏离了这里的主要问题。如果您真的想问这个问题,请编辑您的问题。

标签: java jvm


【解决方案1】:

java memory model的第一个点是:

线程中的每个动作都发生在该线程中的每个动作之前 它在程序的顺序中稍后出现。

这就是为什么在单线程中重新排序是不可能的。只要代码不同步,就不会为多线程提供此类保证。

看看 String hashCode 的实现。它首先将哈希加载到局部变量,然后才执行检查和返回。这就是防止这种重新排序的方式。但这并不能让我们免于多次 hashCode 计算。

【讨论】:

  • 我相信在单线程程序中不会阻止重新排序。它只是不会在单线程中被注意到。
【解决方案2】:

第一个问题:

指令的重新排序会发生在单线程执行中吗?

答案:

指令的重新排序是一种编译器优化。无论涉及多少个线程,一个线程中的指令顺序都是相同的。或者:在单线程中也是。

第二个问题:

为什么这会导致多线程而不是单线程的问题?

答案:

这种重新排序的规则旨在确保在单线程或正确同步的代码中没有奇怪的影响。这意味着:如果我们编写的代码既不是单线程也不是正确同步的,可能会出现奇怪的影响,我们必须了解规则并注意避免这些影响。

正如原始博客的作者所说:如果您不确定是否了解这些规则,请不要尝试。并且每个编译器都将经过测试以不破坏 String.hashCode() 但不会使用您的代码测试编译器。

编辑: 第三个问题:

究竟发生了什么?

答案:

当我们查看代码时,它会很好地处理看不到另一个线程的变化。所以我们首先要了解的是:方法不返回变量、常量或文字。当程序计数器重置时,没有方法返回堆栈顶部的内容。这必须在某个时间点初始化,以后可以覆盖。这意味着它可以首先使用hash(现在为0)的内容进行初始化,然后另一个线程完成计算并将hash设置为某个值,然后检查hash == 0。反过来,返回值不再被覆盖,而是返回 0。

所以重点是:返回值可以独立于返回的变量而改变,因为它不一样。现代编程语言让它看起来一样,让我们​​的生活更轻松。但是当你不遵守规则时,这个抽象是一个整体。

【讨论】:

  • 在单线程环境下可能会发生重新排序,但不会产生意外的行为,因为意外的行为是由于在其他线程中修改了字段,而当前线程已优化并没有查看更新后的值。
  • @nhahtdh 希望我的编辑能更清楚一点。
  • check hash == 0 happens 的具体表现在哪里?
  • 我一直相信check hash == 0 会首先将哈希加载到线程堆栈的顶部(这会覆盖返回值),不是吗?
  • 不,比较不是方法调用。它不会使用堆栈,而是使用处理器寄存器。寄存器的比较是单处理器指令。实际上,返回值在返回之前保存在寄存器中。但是,寄存器或堆栈不是重点。关键是,返回的内容与变量无关。
猜你喜欢
  • 2013-10-19
  • 2018-08-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-07-30
  • 1970-01-01
  • 1970-01-01
  • 2017-01-31
相关资源
最近更新 更多