“条件”时“无所事事”

时间:2014-07-07 11:30:22

标签: java while-loop do-while

在浏览ForkJoinPool的Java 8版本的代码时(我从Java 7中进行了一些有趣的更改),我遇到了这个构造(here):

do {} while (!blocker.isReleasable() &&
             !blocker.block());

我正在努力解决为什么你会这样写,而不仅仅是

while (!blocker.isReleasable() &&
       !blocker.block());

它只是一个语义/可读性选择,因为你可以将第一个结构读作do "nothing" while "conditions"吗?或者我还缺少一些额外的好处吗?

5 个答案:

答案 0 :(得分:54)

如果你阅读文件顶部的注释,就在类声明的下面,有一节解释了这个结构的用法:

Style notes

===========

[...]

There are several occurrences of the unusual "do {} while
(!cas...)"  which is the simplest way to force an update of a
CAS'ed variable. There are also other coding oddities (including
several unnecessary-looking hoisted null checks) that help
some methods perform reasonably even when interpreted (not
compiled).

答案 1 :(得分:45)

ForkJoinPool广泛使用来自compareAndSwap...的{​​{1}},并且sun.misc.Unsafedo {} while (...)的大部分事件都可以 - 正如其他答案所述 - 解释通过标题样式注释下的这个评论:

ForkJoinPool

选择使用写* There are several occurrences of the unusual "do {} while * (!cas...)" which is the simplest way to force an update of a * CAS'ed variable. - 循环,空体为while似乎是一个主要的风格选择。这在do {} while (condition)中可能更清楚,它恰好在Java 8中更新。

在Java 7 HashMap中,您可以找到:

HashMap

虽然围绕它的大部分代码也发生了变化,但很明显Java 8中的替换是这样的:

while (index < t.length && (next = t[index++]) == null)
    ;

第一个版本的缺点是,如果删除了单独的分号,它将根据以下行改变程序的含义。

如下所示,do {} while (index < t.length && (next = t[index++]) == null); while (...) {}生成的字节码略有不同,但在运行时不会以任何方式影响任何内容。

Java代码:

do {} while (...);

生成的代码:

class WhileTest {
    boolean condition;

    void waitWhile() {
        while(!condition);
    }

    void waitDoWhile() {
        do {} while(!condition);
    }
}

答案 2 :(得分:8)

除了任何潜在的性能优势外,还有明显的可读性优势。

使用while (X) ;乍一看并不总是显而易见的分号,您可能会对以下语句或语句在循环内部感到困惑。例如:

while (x==process(y));
if (z=x) {
    // do stuff.
}

很容易误解上面的内容,因为在循环中有if语句,即使你确实正确地读了它,也很容易认为这是编程错误而if应该在循环内部。

使用do {} while(X);虽然可以立即一目了然地知道循环没有身体。

答案 3 :(得分:4)

如果您将阅读代码上方的评论,则会提到......

如果调用者不是ForkJoinTask,则此方法在行为上等同于

while (!blocker.isReleasable())
   if (blocker.block())
      return;
}

所以这只是在else部分实现上述代码的另一种形式...... !!

Style notes中提到了

  

有几次异常&#34; do {}同时发生    (!CAS ...)&#34;这是强制更新a的最简单方法    CAS&#39; ed变量。

如果你看到ManagedLocker#isReleasable的实现,它正在更新锁,如果不需要阻止,则返回true

解读:

空白while循环用于提供中断,直到某些条件重置为true / false。

此处,do { } while(!...)blocker.block() true blocker.isReleasable() false blocker时阻塞/中断。!blocker.isReleasable()循环将继续执行而blocker不可释放(blocker.block())且do{ } while(...)未被阻止! <{1}}设置为true后,执行将不再循环。

请注意,{{1}}不更新CAS变量,但它保证程序将等到变量更新(强制等待变量更新)。

答案 4 :(得分:0)

您可以使用以下方式轻松制作以下内容:

if(true){
 //Do nothing ...
}