有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java在“条件”时“不做任何事情”

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

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

我在琢磨你为什么要这样写,而不是仅仅

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

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


共 (5) 个答案

  1. # 1 楼答案

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

    使用while (X) ;后接分号乍一看并不总是明显的,您可能会误以为以下语句在循环中。例如:

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

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

    使用do {} while(X);尽管一眼就能看出循环中没有主体

  2. # 2 楼答案

    如果您阅读代码上面的注释,就会发现

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

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

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

    在{a1}中提到

    There are several occurrences of the unusual "do {} while (!cas...)" which is the simplest way to force an update of a CAS'ed variable.

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

    解释:

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

    这里,do { } while(!...)是一个阻断器/中断,直到blocker.block()trueblocker.isReleasable()false时。循环将在blocker不可发布(!blocker.isReleasable())且blocker未被阻止时继续执行!!一旦blocker.block()设置为true,执行将脱离循环

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

  3. # 3 楼答案

    您可以使用以下工具轻松制作类似的内容:

    if(true){
     //Do nothing ...
    }
    
  4. # 4 楼答案

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

    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).
    
  5. # 5 楼答案

    ForkJoinPool广泛使用了来自sun.misc.UnsafecompareAndSwap...,并且do {} while (...)ForkJoinPool中出现的大多数do {} while (...)可以通过标题下的注释解释,正如其他答案所述:

    * 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 (condition)while-循环似乎是一种风格上的选择。这在{}中可能更清楚,它碰巧在Java8中更新了

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

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

    虽然它周围的许多代码也发生了变化,但很明显,Java 8中的替代品是:

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

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

    如下所示,由while (...) {}do {} while (...);生成的字节码略有不同,但在运行时不会产生任何影响

    Java代码:

    class WhileTest {
        boolean condition;
    
        void waitWhile() {
            while(!condition);
        }
    
        void waitDoWhile() {
            do {} while(!condition);
        }
    }
    

    生成的代码:

    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        
    }