2010-12-11 5 views
0

Как выглядит следующий демо-код? Мы гарантируем, не изменится ли значение в инструкции CAS, а затем выполняется инкремент по int. Не делает return v + 1; шаг, избили всю цель, поскольку он может пропустить обновления потоков.Использование compareAndSet для обеспечения безопасности нитей

Здесь атомное целое используется для имитации неблокирующего счетчика int.

//Here value is an atomic integer 
public int increment() 
{ 
    int v; 
    for(;;) 
    { 
     v = value.get(); 
     if(value.compareAndSet(v, v + 1)) 
     return v + 1; 
    } 
} 

не должны код выглядеть так:

public int increment() 
{ 
    int v; 
    for(;;) 
    { 
     v = value.get(); 
     if(value.compareAndSet(v, v + 1)) 
     return value.get(); 
    } 
} 

ответ

5

compareAndSet() возвращает true, если текущее значение равно ожидаемому значению v, и, таким образом, значение было обновлено до v + 1.

В вашей первой версии, если оба потока получают начальное значение же тогда один преуспеет (обновление до v + 1), а другой не удастся (так как текущее значение больше не v) и повторите попытку использования v + 1 и v + 2.

Если этот код предназначен для возврата уникальных ключей, то первая версия верна, так как в точке compareAndSet() возвращается true текущее значение гарантировано v + 1 (даже если только на короткое время). Вторая версия может возвращать повторяющиеся значения из-за состояния гонки, если другой поток изменяет значение между вашими вызовами до compareAndSet() и get().

Это, пожалуйста, вы должны изучить метод AtomicIntegerincrementAndGet(), который делает практически то же самое, но более эффективно (без явного цикла).

2

Определить "работу".

Предположим, что value изначально нулевой. Если первая функция называется 100 раз, она вернет каждое число от 1 до 100 ровно один раз. Вторая функция не обладает этим свойством.

Обе функции могут выдавать значения, устаревшие к моменту возвращения функции.

Что более «правильно» действительно зависит от ожидаемой семантики increment.

Смежные вопросы