2016-08-06 8 views
1

次のコードは、あるスレッドが別のスレッドがすでに更新かもしれないcurrent取得した後Javaで競合状態が発生しないで原子変数を同時に更新することはなぜ可能ですか?

ここ
AtomicInteger atomicInt = new AtomicInteger(0); 

ExecutorService executor = Executors.newFixedThreadPool(20); 

IntStream.range(0, 1000) 
    .forEach(i -> executor.submit(atomicInt::incrementAndGet)); 

は、我々はcurrentが同期またはロックされていない見ることができますincrementAndGet

public final int incrementAndGet() { 
    for (;;) { 
     int current = get(); 
     int next = current + 1; 
     if (compareAndSet(current, next)) 
      return next; 
    } 
} 

の実装である競合条件なしで動作します。

しかし、それは原子クラスが競合状態を回避するように思われます。

私の間違いを指摘できますか?

+0

compareAndSet()はロックを使用します。ほとんどの実装では、 'compareAndSet()'は、ハードウェア(例えば、x86ハードウェア上のCMPXCHG命令)におけるロックを行う特別な命令を実行する。https://en.wikipedia.org/wiki/Compare-and-swap –

答えて

3

compareAndSetは、最初のパラメータがAtomicIntegerの現在の値と等しい場合に限り、値を設定し(trueを返します)。

つまり、別のスレッドがすでに値を変更していた場合、currentは現在の値と等しくなくなり、ループがもう一度実行されます。 compareAndSet(int expect, int update)documentationから

:現在 値場合

原子的には、期待値==指定された更新値に値を設定します。

関連する問題