Стандарт говорит (цитируя последний проект):
[введение.гонки]
Два вычисления выражения конфликтуют, если одно из них изменяет ячейку памяти ([intro.memory]), а другая читает или изменяет ту же ячейку памяти.
Выполнение программы содержит гонку данных, если она содержит два потенциально параллельных конфликтующих действия, хотя бы одно из которых не является атомарным и ни одно из них не происходит раньше другого, за исключением особого случая для обработчиков сигналов, описанного ниже. Любая такая гонка данных приводит к неопределенным действиям.
В вашей примерной программе есть гонка данных, и поведение программы не определено.
Чего я не понимаю, так это того, как порядок операций имеет значение в этом примере.
Порядок операций имеет значение, потому что операции не являются атомарными, и они считывают и изменяют одну и ту же ячейку памяти.
можно понять, что порядок имеет значение, если бы я использовал va = va + 1; потому что тогда RHS va могла измениться, прежде чем вернуться к назначенному LHS va
То же самое относится и к оператору приращения. Абстрактная машина будет:
- Чтение значения из памяти
- Увеличить значение
- Записать значение обратно в память
Там есть несколько шагов, которые могут чередоваться с операциями в другом потоке.
Даже если бы в каждом потоке была одна операция, не было бы гарантии четко определенного поведения, если бы эти операции не были атомарными.
Примечание, выходящее за рамки C++: ЦП может иметь одну инструкцию для увеличения целого числа в памяти. Например, у x86 есть такая инструкция. Его можно вызывать как атомарно, так и неатомарно. Для компилятора было бы расточительно использовать атомарную инструкцию, если вы явно не используете атомарные операции в C++.
person
eerorika
schedule
04.09.2019
va
одновременно, даже внутри циклов for. Кто выигрывает? Неизвестно, поэтому окончательное значениеva
может быть любым. - person Ripi2   schedule 04.09.2019va
действительно будут перемещены в место, где их смогут увидеть другие потоки. Например,va
вполне может храниться в регистре. - person François Andrieux   schedule 04.09.2019va += 10000;
,va += 10000;
, что еще больше снижает шансы увидеть эффект гонки. - person Jarod42   schedule 04.09.2019va = 0;
, а другойva = 1;
, тогда даже в правильном коде (без гонки данных) вы не обязательно будете знать, какой поток будет первым. - person 463035818_is_not_a_number   schedule 04.09.2019