Как AtomicInteger является поточно-ориентированным - PullRequest
1 голос
/ 20 мая 2019

Я читал некоторые документы об атомарных переменных в Java.Как написано везде, AtomicInteger считается поточно-ориентированным.

Согласно моему пониманию атомных целых чисел, он работает по принципу Compare и Swap алгоритм.Я не могу понять, как это будет работать в случае, когда два потока пытаются увеличить одну и ту же атомарную переменную в одно и то же время.

говорят, что я определил AtomicInteger var = 1, и это используется двумя потоками Thread_1 и Thread_2.Что произойдет, когда оба потока попытаются увеличить var одновременно T1.Я знаю, что это будет редкая ситуация, но что, если это произойдет.При сравнении и обмене он считывает и обновляет переменную в одной атомарной операции и проверяет значение из памяти.так что если в момент времени T1-1 значение var равно 5 и оба Thread1 и Thread2 начнут увеличивать его?Какой из них потерпит неудачу?Это будет случайное поведение?или я упускаю что-то очень простое.

Ответы [ 3 ]

5 голосов
/ 20 мая 2019

Сравнение и своп являются атомарными на уровне ЦП.

Вы можете явно выполнить операцию инкремента с помощью сравнения и свопинга:

int value = var.get();
while (!var.compareAndSwap(value, value + 1)) { 
  value = var.get();
}

ЦП гарантирует compareAndSwapбыть атомарным (будет собственная реализация этого).

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

Другой поток «проиграет» и получит false в результате, и поэтому снова обойдет цикл: он читает новое значение, а затемпробует CAS снова.Если это удается (потому что либо другой поток не пытался сделать это одновременно, либо он «выиграл» над другим потоком), цикл останавливается;в противном случае он просто пытается снова.

2 голосов
/ 20 мая 2019

что, если в момент времени T1-1 значение var равно 5, и Thread1 и Thread2 начнут увеличивать его?

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

Даже если они работают на разных ядрах и операция CAS выполняется точно в одно и то же время, все равно одна из операций завершится неудачно, которая фактически является случайной (может не зависеть от реализации ЦП).

2 голосов
/ 20 мая 2019

Это типичная ситуация с расой. Рассмотрим эту операцию приращения как маленькую комнату с маленькой дверью, в которую может уместиться только один человек и выполнить некоторые операции. Первый поток из двух, кому удастся войти в эту комнату, будет выполнять операцию приращения. Затем, когда это закончится, второй = "менее удачный" поток выполнит свою работу. Но важно то, что результат обеих операций согласован с точки зрения того, что они не выполняют операции приращения параллельно.

...