Являются ли приращения/декременты (var ++, var--) и т.д. Безопасными?
Вдохновленный этим вопросом: В анализе сложности почему ++ считается 2-мя операциями?
Возьмите следующий код psuedo:
class test
{
int _counter;
void Increment()
{
_counter++;
}
}
Будет ли это считаться потокобезопасным на x86-архитектуре? Кроме того, инструкции по сборке Inc/Dec потокобезопасны?
Ответы
Ответ 1
Нет, приращение не является потокобезопасным. Также нет инструкций INC
и DEC
. Все они требуют загрузки и хранения, а поток, запущенный на другом ЦП, может выполнять свою собственную загрузку или хранить в том же месте памяти, перемежаемом между этими операциями.
Некоторые языки имеют встроенную поддержку синхронизации потоков, но обычно это то, о чем вы должны попросить, а не то, что вы автоматически получаете по каждой переменной. Те, у кого нет встроенной поддержки, обычно имеют доступ к библиотеке, которая обеспечивает аналогичную функциональность.
Ответ 2
Одним словом, нет.
Вы можете использовать что-то вроде InterlockedIncrement()
в зависимости от вашей платформы. В .NET вы можете использовать методы класса Interlocked
(например, Interlocked.Increment()
).
A упомянул Роб Кеннеди, даже если операция реализована в терминах одной инструкции INC
, поскольку в памяти используется чтение/приращение/записывается набор шагов. Существует возможность использования многопроцессорной системы для коррупции.
Также существует проблема с volatile
, которая была бы необходимой частью обеспечения безопасности потока операций, однако маркировка переменной volatile
недостаточна, чтобы сделать ее потокобезопасной. Используйте поддерживаемую платформой поддержку.
Это верно в целом и на платформах x86/x64.