std :: atomic <int>декремент и сравнение - PullRequest
19 голосов
/ 26 октября 2011

На следующий код:

std::atomic<int> myint; //Shared variable
//(...)
if( --myint == 0) {
    //Code block B
}

Возможно ли, что более одного потока обращаются к блоку, который я назвал "Блок кода B"?

Обратите внимание, что переполнения не произойдет, что 'if' выполняется одновременно более чем одним потоком, что единственное изменение myint во всей программе - это - myint внутри if и что myint инициализируется положительным значением.

Ответы [ 3 ]

18 голосов
/ 27 октября 2011

C ++ 0x paper N2427 (атомика) гласит примерно следующее. Я немного изменил формулировку, чтобы ее было легче читать для конкретной ситуации декремента, части, которые я изменил, выделены жирным шрифтом :

Эффекты: Атомно заменить значение в объект результатом декремента , примененного к значению в объект и данным операнд. Память влияет на порядок. Эти операции являются операциями чтения-изменения-записи в смысле определения «синхронизируется с» в [новом разделе, добавленном N2334 или преемником], и, следовательно, и такая операция, и оценка, которая произвела входное значение, синхронизируются с любой оценкой, которая читает обновленное значение.

Возвращает: Атомно, значение объекта непосредственно перед декрементом .

Атомная операция гарантирует, что оператор декремента вернет значение, которое переменная содержала непосредственно перед операцией, это атомарное, поэтому не может быть промежуточного значения из обновлений другим потоком.

Это означает, что единственные возможные варианты выполнения этого кода с двумя потоками:

(Initial Value: 1)
Thread 1: Decrement 
Thread 1: Compare, value is 0, enter region of interest
Thread 2: Decrement
Thread 2: Compare, value is -1, don't enter region

или

(Initial Value: 1)
Thread 1: Decrement 
Thread 2: Decrement
Thread 1: Compare, value is 0, enter region of interest
Thread 2: Compare, value is -1, don't enter region

Случай 1 - неинтересный ожидаемый случай.

Случай 2 перемежает операции декремента и выполняет операции сравнения позже. Поскольку операция декремента и выборки atomic , поток 1 не может получить значение, отличное от 0, для сравнения. не может получить -1, потому что операция была атомарной ... чтение происходит во время декремента, а не во время сравнения. Другие темы не изменят это поведение.

2 голосов
/ 27 октября 2011

Не очевидно, что блок кода будет выполняться всегда.Если оператор «-» реализован таким образом, что он сохраняет старое значение в возвращаемом значении и уменьшает значение в одной атомарной инструкции (я почти уверен, что в x86 есть такие инструкции), тогда да, он должен действовать какблок взаимного исключения для нескольких потоков.Я не уверен, как это работает по умолчанию, но ответ, вероятно, лежит в новой стандартной документации:

http://www.open -std.org / jtc1 / sc22 / wg21 / docs /apers / 2007/n2427.html

0 голосов
/ 27 октября 2011

Нет, возможно, что более одного потока входит в блок, учитывая ваши ограничения. Но также не гарантируется, что какой-либо поток когда-либо попадет в этот блок:

thread A: decrement myint to 0

thread B: decrement myint to -1

thread A: compare to 0 -> false -> don't enter (and neither anyone else)

Если это проблема (которую я предполагаю), то этот код не будет работать (по крайней мере, не всегда ).

...