8

while と do-while

while と do-while は、ブロックが空の場合は機能的に同等ですが、 while の方が自然に見えます:

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

空のブロックを使用した while/do-while の典型的な使用例の 1 つは、compareAndSet (CAS) を使用してアトミック オブジェクトを強制的に更新することです。たとえば、次のコードaはスレッドセーフな方法でインクリメントします。

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

環境

java.util.concurrent のいくつかの部分ではdo {} while (...)、CAS 操作にイディオムを使用しており、javadoc で次のようにForkJoinPool説明されています。

do {} while (!cas...)CAS された変数の更新を強制する最も簡単な方法である異常な現象がいくつか発生します。

彼らはそれが異常であることを認めているので、彼らは最も単純というよりも最良を意味していたと思います。

質問

do {} while (!cas)よりも効率的な状況はありwhile (!cas) {}ますか?その理由は何ですか?

4

3 に答える 3

2

したがって、「do while」は、while ループでコードを 1 回実行することを意味します。次に、条件が true の場合にのみ while ループ内のコードを実行します。

簡単なデモンストレーション

boolean condition = false;

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

「このテキストが表示されました」を出力

普通

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

出力 ""

  • *条件が false であるため、出力は表示されません。

do while を使用する理由または場所については、その必要性に遭遇していないため、その点についてはお答えできません。問題/ニーズを特定し、それを解決するために知っていることを使用するだけの問題です.レゴに似ています-「ブロック」ではなく機械的な種類.

于 2014-10-09T15:38:58.883 に答える
0

これは効率の問題ではありません。do{}while() なしでは解決できないケースもあります。{} java.util.Random.next(int ビット) を見てください。while(){} で同じことをしようとすると、条件の前にサイクル本体を 1 回実行する必要があるため、コードが重複します。

私はすでに非常によく似た質問をしました: Java でループをコンパイルしています。

このコード:

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);
    }
}

次のようにコンパイルされます。

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

method1() の 13 行目に追加の指示があることに気付くかもしれません。しかし、私の質問の回答で示唆されたように、これは JIT によって機械語命令にコンパイルされた場合、何の違いもありません。非常にとらえどころのないパフォーマンスの向上。それを証明するには、PrintAssembly キーで実行する必要があります。理論的には method2 の方が高速ですが、実際には同じになるはずです。

于 2013-05-08T11:00:56.177 に答える
0

expect と update の計算が複雑すぎて、compareAndSet を呼び出すのと同じ行で読むことができない状況があったかもしれません。次に、do 内で読みやすくすることができます。

do {
  int expect = a.get();
  int update = expect + 1;
} while (!a.compareAndSet(expect, update));
于 2013-05-08T10:12:35.570 に答える