Java 在“条件”时“无所事事”

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/24609564/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-14 13:26:03  来源:igfitidea点击:

Do "nothing" while "condition"

javawhile-loopdo-while

提问by Erik Vesteraas

While browsing the code for the Java 8 version of ForkJoinPool(which has a few interesting changes from Java 7) I ran across this construct (here):

在浏览 ForkJoinPool 的 Java 8 版本(与 Java 7 相比有一些有趣的变化)的代码时,我遇到了这个构造(这里):

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

I'm struggling with why you would write it like this instead of just

我在为你为什么要这样写而不只是这样写而苦苦挣扎

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

Is it just a semantics/readability choice, since you could read the first construct as do "nothing" while "conditions"? Or is there some additional benefit I'm missing?

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

采纳答案by MicSim

If you read the comments at top of the file, just below the class declaration, there is a section which explains the use of this construct:

如果您阅读文件顶部的注释,就在类声明的下方,有一个部分解释了此构造的使用:

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).

回答by Not a bug

If you will read comment above the code, It is mentioned that...

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

If the caller is not a ForkJoinTask, this method is behaviorally equivalent to

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

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

So it is just another form to implement above code in else part...!!

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

In Style notesit is mentioned that,

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.

有几次不寻常的“do {} while (!cas...)”,这是强制更新 CAS 变量的最简单方法。

And if you will see implementation of ManagedLocker#isReleasable, It is updating the lock and returns trueif blocking is unnecessary.

如果您将看到ManagedLocker#isReleasable 的实现,它会更新锁并true在不需要阻塞时返回。

Interpretation :

解释 :

Blank while loops are used to provide an interrupt until some condition reset to true/false.

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

Here, do { } while(!...)is a blocker/interrupt until blocker.block()will be truewhen blocker.isReleasable()is false. Loop will continue execution while blockeris not releasable (!blocker.isReleasable()) and blockeris not blocked !! Execution will be out of loop as soon as blocker.block()will set to true.

这里,do { } while(!...)是一个阻塞程序/中断,直到blocker.block()将是true什么时候blocker.isReleasable()false。循环将在blocker不可释放 ( !blocker.isReleasable())blocker且未被阻塞时继续执行!!blocker.block()设置为 true后,执行将退出循环。

Note that, do{ } while(...)does not update CAS variable, but it guarantee that program will wait until variable gets updated (force to wait until variable gets updated).

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

回答by Erik Vesteraas

ForkJoinPoolmakes extensive use of compareAndSwap...from sun.misc.Unsafeand most of the occurrences of do {} while (...)in ForkJoinPoolcan — as mentioned by other answers — be explained by this comment under the heading Style notes:

ForkJoinPool广泛使用compareAndSwap...fromsun.misc.Unsafe并且大多数do {} while (...)in的出现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. 
* There are several occurrences of the unusual "do {} while
* (!cas...)"  which is the simplest way to force an update of a
* CAS'ed variable. 

The choice to use write a while-loop with an empty body as do {} while (condition)seems however to be a mostly stylistic choice. This is perhaps clearer in HashMap, which happened to be updated in Java 8.

然而,选择使用 write a while-loop with a empty bodydo {} while (condition)似乎是一个主要的风格选择。这在 中可能更清楚HashMap,它恰好在 Java 8 中更新。

In the Java 7 HashMapyou can find this:

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

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

While much of the code around it has also changed, it is clear that the replacement in Java 8 is this:

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

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

The first version has the weakness that if the lone semicolon happened to be deleted it would change the meaning of the program depending on the following line.

第一个版本有一个弱点,如果单独的分号碰巧被删除,它会改变程序的含义,具体取决于以下行。

As seen below, bytecode generated by while (...) {}and do {} while (...);is slightly different, but not in any way that should affect anything when run.

如下所示,由while (...) {}和生成的字节码do {} while (...);略有不同,但不会以任何方式影响运行时的任何内容。

Java code:

爪哇代码:

class WhileTest {
    boolean condition;

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

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

Generated code:

生成的代码:

class WhileTest {
  boolean condition;

  WhileTest();
    Code:
       0: aload_0       
       1: invokespecial #1                  // Method java/lang/Object."<init>":()V
       4: return        

  void waitWhile();
    Code:
       0: aload_0       
       1: getfield      #2                  // Field condition:Z
       4: ifne          10
       7: goto          0
      10: return        

  void waitDoWhile();
    Code:
       0: aload_0       
       1: getfield      #2                  // Field condition:Z
       4: ifeq          0
       7: return        
}

回答by Tim B

Leaving aside any potential performance benefits, there is a clear readability benefit.

撇开任何潜在的性能优势不谈,还有一个明显的可读性优势。

With while (X) ;the trailing semicolon is not always obvious at first glance, you may be confused into thinking that the following statement or statements are inside the loop. For example:

由于while (X) ;尾随分号乍一看并不总是很明显,您可能会误以为以下语句或语句在循环内。例如:

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

It would be very easy to misread the above as having the if statement inside the loop, and even if you did read it correctly it would be easy to think that it was a programming mistake and the if should be inside the loop.

很容易将上面的内容误读为在循环中包含 if 语句,即使您没有正确阅读它,也很容易认为这是一个编程错误并且 if 应该在循环中。

With do {} while(X);though it is immediately at a glance clear that there is no body to the loop.

随着do {} while(X);虽然它立即一目了然,没有身体的循环。

回答by user6765242

You can easily make something like this with:

你可以很容易地做这样的事情:

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