In what situations can do-while be more efficient

2020-07-09 06:27发布

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?

3条回答
2楼-- · 2020-07-09 07:11

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.

查看更多
姐就是有狂的资本
3楼-- · 2020-07-09 07:13

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));
查看更多
beautiful°
4楼-- · 2020-07-09 07:22

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

查看更多
登录 后发表回答