问题
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