Страницы

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

среда, 9 января 2019 г.

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

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


Ответ

Так делать нельзя. Операции с 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

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

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