Как вы говорите, это условие гонки. В C ++ 11 это технически гонка данных и неопределенное поведение. Неважно, что значения одинаковы.
Если ваш компилятор поддерживает его (например, недавний gcc, или gcc или MSVC с моей библиотекой Just :: Thread ), тогда вы можете использовать std::atomic<some_pod_struct>
, чтобы обеспечить атомарную оболочку вокруг ваших данных (при условии, что это - это структура POD - если нет, то у вас есть большие проблемы). Если он достаточно мал, то компилятор освободит его от блокировки и будет использовать соответствующие атомарные операции. Для больших структур библиотека будет использовать блокировку.
Проблема с выполнением этого без атомарных операций или блокировок - visibility . Хотя на уровне процессора на x86 или ARM нет проблем с записью одних и тех же данных (при условии, что они действительно идентичны побайтно) из нескольких потоков / процессоров в одну и ту же память, учитывая, что это кэш, я ожидаю Вы захотите прочитать эти данные, а не пересчитать их, если они уже были записаны. Поэтому вам понадобится какой-то флаг, чтобы указать готовность. Если вы не используете атомарные операции, блокировки или подходящие инструкции по блокировке памяти, тогда флаг «готовности» может стать видимым для другого процессора до того, как сделает данные. Это тогда действительно испортит ситуацию, поскольку второй процессор теперь читает неполный набор данных.
Вы можете записать данные с неатомарными операциями, а затем использовать атомарный тип данных для флага. В C ++ 11 это создаст подходящие барьеры памяти и синхронизацию, чтобы гарантировать, что данные видны любому потоку, который видит установленный флаг. Для двух потоков все еще не определено поведение при записи данных, но на практике это может быть нормально.
В качестве альтернативы, храните данные в блоке памяти кучи, выделенной каждому потоку, который выполняет вычисления, и используйте операцию сравнения и замены, чтобы установить переменную атомного указателя. Если сравнение и замена завершаются неудачно, то сначала туда попадает другой поток, поэтому освободите данные.