【问题标题】:Two parallel increment and decrement terminating when equal两个并行递增和递减相等时终止
【发布时间】:2014-01-30 23:32:49
【问题描述】:

假设您有以下两个过程:

var x = 0;
var y = 10;
def P = { while (x != y) x = x + 1; }
def Q = { while (x != y) y = y - 1; }

并行运行。

唯一的原子操作是 READ、INCREMENT、DECREMENT、WRITE。

我想有一种情况是一个进程“跳过”另一个进程(因为您无法控制它们的运行方式)。

这是一个例子:

  • P 和 Q READ x = 0, y = 10(最开始)
  • Q 跑得很快,使 y 达到 0
  • P 递增和写入,现在 x 为 1(因为它仍然认为 y 为 10)
  • 回到 Q,将 x 读为 1,将 y 读为 0
  • Q 将 y 递减到 -1
  • 永不终止

为什么没有发生呢?它似乎总是终止。

有人可以解释为什么我的例子没有发生吗?

【问题讨论】:

  • 增量和减量是原子的?不在JVM上,我不相信。即使您的代码编译为 iinc 也不行。从 RAM 读取、计算新值并将其写回绝不是原子操作。
  • @RandallSchulz 嗯,我将增量/减量与读写分开。
  • 您可能想这样想它们,但事实并非如此。递增和递减是先读后写,基本上不是原子的。为了澄清,递增本身只发生在处理器寄存器中。
  • @RandallSchulz 我的问题确实很差,因为我没有展示完整的实现。但是,关于您的评论,我认为您看不到我的意思。我说过很多次,我将读写与递增和递减分开。这实际上就是您所说的“它们发生在处理器寄存器中”,是的。一个“完整”的增量,我将其定义为 read + incrememnt_in_processor + write。这三个中的每一个都是原子的,所以整体的完整增量显然不是原子的。
  • 原子性的概念是关于在一个执行线程与另一个执行线程之间或一个处理器与另一个处理器之间可以观察到的内容。严格在处理器内发生的动作根据定义是在这种观察之外的。因此,根据定义,“增量”和“减量”要么不是原子的,要么与原子性无关。但它们不是原子的!

标签: java scala parallel-processing


【解决方案1】:

我最初打算否决这个问题,但它给了我复杂的感觉,因为一方面这不是一个措辞恰当的问题:你使用什么并发框架?你确定你在做正确的事——它真的是并发的吗?我们怎么能在没有看到更多代码的情况下判断。这些关于原子性的假设是什么?您是否在某种没有真正并发的 VM 中的单个线程上实际运行它?我怎么知道这一切?你真的只跑到数到 10 吗?我什至在乎吗?我应该关心吗? ...

...不过我还是应该指出这一点:

这个循环会终止吗?:

var x = 1; while(x>0){ x = x + 1 }

或类似的问题 - Int.MaxValue + 1 的值是多少?

这是对您问题的部分回答......另一部分我不太关心;)

【讨论】:

    【解决方案2】:

    总的来说,我喜欢您的问题,但您必须提供真正的源代码,以便我们提供帮助。一种可能的答案是优化。 P 循环中 y 的值可以“缓存”在处理器寄存器中,而不必包含内存中的当前值。

    在 Java 中,您可以通过 volatile 关键字解决此问题: http://docs.oracle.com/javase/tutorial/essential/concurrency/atomic.html

    在 Scala 中有一个 volatile 注释: http://www.scala-lang.org/old/node/7952.html

    尝试将println(y) 添加到 P 循环中,以便查看 y 的值是否(以及如何)发生变化。继续努力。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-04-29
      相关资源
      最近更新 更多