Как выполнить сравнение и приращение атомарно?
-
24-09-2019 - |
Вопрос
В моей попытке разработать потокобезопасный класс шаблона слабого указателя C ++ мне нужно проверить флаг, указывающий, что объект все еще активен, если да, то увеличьте количество ссылок на объект, и мне нужно выполнить оба шага атомарно.
Я знаю о существовании встроенных функций, предоставляемых компилятором, например _InterlockedCompareExchange() и _InterlockedIncrement().Но то, что я хочу, это функция interlockedCompareIncrement(), есть ли эффективный способ имитировать эту внутреннюю функцию с использованием других примитивов, по крайней мере, на платформе Windows x86?
Решение
Предположим , что value
это ваша переменная flag.Это должно быть объявлено volatile
.
long curvalue;
long newvalue;
do
{
curvalue = value;
newvalue = curvalue + 1;
}
while( _InterlockedCompareExchange( &value, newvalue, curvalue ) != curvalue );
Как вы видите, вы можете обобщить это на любой вид арифметики, который вам нужен, изменив операции, применяемые для вычисления newvalue
.
Если вы хотите сравнить два значения одновременно, лучше всего упаковать оба значения в одну переменную, а затем оперировать с этой единственной переменной.Поскольку вы используете флаг в сочетании с количеством ссылок, я бы рекомендовал использовать наименьший бит value
как флаг 'alive', а затем увеличивайте / уменьшайте на 2 за раз.Это позволяет вам закодировать как флаг, так и количество ссылок в одну 32-разрядную переменную.
Другие советы
Если вы хотите, чтобы ваша библиотека запустилась на нескольких CPU или нескольких основных машинах, вы должны использовать аппаратную поддержку, предоставляемую CPU. Вот некоторые ссылки для вас:
http://en.wikipedia.org/wiki/test-and-set. http://software.intel.com/en-us/forums/showthread.php?t=47498.
Или вам необходимо использовать блокирующий механизм, предоставляемый ОС. Такие как
http://msdn.microsoft.com/en-us/library/ms684841%28vs.85%29.aspx.илиhttp://en.wikipedia.org/wiki/posix_threads.
Поскольку вы находитесь в C ++, вы можете написать свой собственный код сборки.
Возможно, это связано с Воспользуйтесь атомным приращением с помощью атомного свопа?