Страницы

Поиск по вопросам

четверг, 2 января 2020 г.

Можно ли использовать volatile переменную для арифметических операций?

#java #многопоточность #volatile


Допустим, есть несколько потоков, они прибавляют некоторые значения в volatile-переменную
(типа синглтон), и выводят значения этой переменной после суммирования в реальном времени
(ну должно быть в реальном времени). Все операции - только с целыми числами.

Можно ли так делать? Какие возникнут проблемы?
    


Ответы

Ответ 1



Так делать нельзя. Операции с volatile-переменной не являются атомарными. Ключевое слово volatile лишь сообщает компилятору о том, что переменная может быть изменена либо извне программы, либо другим потоком и нельзя кэшировать её значение, т.е. значение всегда должно считываться/записываться напрямую в ячейку памяти. В качестве примера рассмотрим выполнение кода i = i + 1; Пусть i == 0 и у нас есть два потока, одновременно выполняющих этот код. Тогда возможна следующая ситуация (regX - регистр процессора): Поток 1 Поток 2 Результат mov regA, [i] | | regA == 0 | mov regB, [i] | regB == 0 | add regB, 1 | regB == 1 | mov [i], regB | i == 1 add regA, 1 | | regA == 1 mov [i], regA | | i == 1 То есть, код выполнился два раза, но переменная i тем не менее увеличилась только на единицу. Если Вам нужен потокобезопасный счётчик, используйте AtomicInteger.

Ответ 2



Если переменной только присваивается или читается значение, то никаких проблем не будет. Но если переменная используется как аккумулятор, то возможны сюрпризы. Так код vlt = vlt + 10 преобразовывается в такой int x = vlt; x = x + 10; vlt = x; Соответственно на момент присваивания vlt = x; в поле может лежать любое значение

Комментариев нет:

Отправить комментарий