0

多くの開発者が知っているように、インクリメント オペレーターはアトミックではありません。

例えば:

public void incrementId(){ // id being an int field
   id++;
}

実際には、これは 3 つの異なる操作に対応します。

int temp = id;
id = id + 1;  
id = temp;

さらに、このメソッドは同様に動作します。

    public void incrementId(){ // id being an int field
       id = id + 1;  // three steps also here
    }

私の質問は:

両方の操作に従うことの舞台裏の本当の違いは何ですか:

id = id + 1; //three steps => non atomic

id = anotherIntVariable + 1; // one step => atomic

コンパイラが最初のステップを 3 つのステップに変換し、他のステップを変換しないようにするのは、どのような概念ですか?

4

2 に答える 2

2

コンパイラが最初のステップを 3 つのステップに変換し、他のステップを変換しないようにするのは、どのような概念ですか?

そうでない場合はid = xyz + 1、次のバイト コードにコンパイルされます。

 7  iload_2 [xyz]
 8  iconst_1
 9  iadd
10  istore_1 [id]

上記が「一歩」ではないことはバイトコードから容易にわかる

于 2012-11-15T12:35:28.537 に答える
1

次のように言うことは何もありません。

id = anotherVariable + 1

3 ステップでは実行されません。しかし、上記のコードを何回実行しても、最終結果は常に同じになります (変数の値idは常にanotherIntVariableプラス 1 になります)。例のようid = id + 1に、以前にid変数に設定された値が新しいid値、およびid競合状態が発生した場合の最終値は、期待したものではない可能性があります。

いくつかのメモ:

  • 複数のスレッドから変数を設定している場合idは、設定方法に関係なく、同期する必要があります。常に、または値がまったく設定されない可能性があります (Java Concurrency in Practice の第 3 章を参照)。idまたは、変数を volatileにすることもできます。
  • idこれは、複数のスレッドから実際にアクセスできる場合にのみ重要です。そうでない場合 (たとえば、idがメソッド内のローカル変数の場合)、ロックなどについて心配する必要はありません。これは、メソッド内に匿名スレッドがある場合でも当てはまります。 final と宣言されたローカル変数にのみアクセスできます。
于 2012-11-15T12:35:21.770 に答える