In what situations can do-while be more efficient than while?

夙愿已清 提交于 2019-12-09 16:08:43

问题


While vs. do-while

While and do-while are functionally equivalent when the blocks are empty, although while seems more natural:

do {} while (keepLooping());
while (keepLooping()) {}

One typical use case of a while/do-while with an empty block is to force an update of atomic objects with a compareAndSet (CAS). For example the code below will increment a in a thread-safe way:

int i;
AtomicInteger a = new AtomicInteger();
while (!a.compareAndSet(i = a.get(), i + 1)) {}

Context

Several parts of java.util.concurrent use the do {} while (...) idiom for CAS operations and the javadoc of ForkJoinPool explains:

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

Since they admit it is unusual, I suppose they meant best rather than simplest.

Question

Are there situations where do {} while (!cas) can be more efficient than while (!cas) {} and for what reasons?


回答1:


So a 'do while' means it will run the code in the while loop once. Then, it only runs the code inside the while loop if the condition is true.

Simple demonstration

boolean condition = false;

do{
  System.out.Println("this text displayed");
}while(condition == true);

Output "this text displayed"

Normal

while(condition == true){
 System.out.Println("this text displayed");
}

output ""

  • *no output displayed due to condition being false.

Why or where you would use do while, I havn't come accross the need to so I can't help you there. It's just a matter of identifying a problem/need, and using what you know to solve it.similar to lego-the mechanical kind not 'blocks'.




回答2:


There might have been situations where the calculation of expect and update is to complex to be readable in same line as you call compareAndSet. Then you may make it more readable inside a do:

do {
  int expect = a.get();
  int update = expect + 1;
} while (!a.compareAndSet(expect, update));



回答3:


This is not a question of efficiency. Some cases just can't be solved without do{}while(). Have look at java.util.Random.next(int bits). If you try to do the same with while(){} you'd have a code duplicate, because cycle body have to be executed once before condition.

I've asked a very similar question already: compiling loops in Java.

This code:

public class Test {

    static int i = 0;

    public static void main(String[] args) {
        method1();
        method2();
    }

    public static void method2() {
        do{}while(++i < 5);
    }

    public static void method1() {
        while(++i < 5);
    }
}

is compiled into:

public static void method2();
  Code:
   0:   getstatic       #4; //Field i:I
   3:   iconst_1
   4:   iadd
   5:   dup
   6:   putstatic       #4; //Field i:I
   9:   iconst_5
   10:  if_icmplt       0
   13:  return

public static void method1();
  Code:
   0:   getstatic       #4; //Field i:I
   3:   iconst_1
   4:   iadd
   5:   dup
   6:   putstatic       #4; //Field i:I
   9:   iconst_5
   10:  if_icmpge       16
   13:  goto    0
   16:  return

You might notice additional instruction on line 13 in method1(). But as was suggested by answer in my question, this does not have any difference when compiled by JIT into machine instructions. Very elusive performance improvement. Any way to prove it you have to run with PrintAssembly key. In theory method2 is faster, but in practice they should be equal.



来源:https://stackoverflow.com/questions/16437751/in-what-situations-can-do-while-be-more-efficient-than-while

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!