2015-09-17 1 views
7

AtomicInteger работает с двумя понятиями: CAS и volatile переменная.Как работает «Сравнить и устанавливать» в AtomicInteger

Использование переменной volatile гарантирует, что текущее значение будет видимым для всех потоков, и оно не будет кэшироваться.

Но я путать над CAS (сравнить, а) концепции, которая описана ниже:

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

Мой вопрос в том, что то, что if(compareAndSet(current, next) возвращается false? Не изменится ли значение? В этом случае то, что будет происходить, когда поток выполняется ниже случай:

private AtomicInteger count = new AtomicInteger(); 
count.incrementAndGet(); 
+0

http://blog.slaks.net/2013-07-22/thread-safe-data-structures/ – SLaks

ответ

10

Атомные объекты делают использование Compare and Swap механизма, чтобы сделать их атомно - то можно гарантировать, что значение было как указано и теперь на новое значение.

Код, который вы отправили, постоянно пытается установить текущее значение на другое, чем раньше. Помните, что другой поток также мог выполнить get и пытается его установить. Если два потока расходятся друг с другом, чтобы изменить значение, возможно, что один из приращений завершится с ошибкой.

Рассмотрим следующий сценарий:

  1. Thread 1 вызывает get и получает значение 1.
  2. Тема 1 вычисляет next как 2.
  3. Тема 2 вызывает get и получает значение 1.
  4. Резьба 2 вычисляет next как 2.
  5. Оба потока пытаются записать значение.

Теперь из Атомикс - только одна нить получится, другой Получать false от compareAndSet и ходить снова.

Если этот механизм не был использован, вполне возможно, что оба потока будут увеличивать значение, приводящее к тому, что выполняется только одно приращение.

Сбивающий с толку бесконечный цикл for(;;) будет работать только в том случае, если многие потоки записывают в переменную одновременно. При очень большой нагрузке он может вращаться несколько раз, но он должен заканчиваться довольно быстро.

5

for (;;) бесконечный цикл, так что это будет просто повторить попытку.