Гарантирует ли следующий код ожидаемое значение счетчика (40 000 000) в соответствии с моделью памяти C ++ 11?( NOT ограничено x86).
#include <atomic>
#include <thread>
using namespace std;
void ThreadProc(atomic<int>& counter)
{
for (int i = 0; i < 10000000; i++)
counter.fetch_add(1, memory_order_relaxed);
}
int main()
{
#define COUNT 4
atomic<int> counter = { 0 };
thread threads[COUNT] = {};
for (size_t i = 0; i < COUNT; i++)
threads[i] = thread(ThreadProc, ref(counter));
for (size_t i = 0; i < COUNT; i++)
threads[i].join();
printf("Counter: %i", counter.load(memory_order_relaxed));
return 0;
}
В частности, координаты ослабленной атомики будут такими, что два потока не будут одновременно считывать текущее значение, независимо увеличивать его, и оба записывать свое увеличенноезначение, фактически потеря одной из записей?
Некоторые строки из спецификации указывают, что счетчик должен постоянно равняться 40 000 000 в приведенном выше примере.
[Примечание: операции, определяющие memory_order_relaxed, ослаблены по отношению к упорядочению памяти.Реализации должны по-прежнему гарантировать, что любой данный атомарный доступ к определенному атомарному объекту будет неделим по отношению ко всем другим атомарным доступам к этому объекту.- примечание конца
.
Атомарные операции чтения-изменения-записи должны всегда читать последнее значение (в порядке изменения), записанное в записи, связанной с чтением-изменением-записать операцию.
.
Все модификации конкретного атомного объекта M происходят в некотором определенном общем порядке, называемом порядком модификации M. Если A и Bмодификации атомного объекта M и A происходят до (как определено ниже) B, тогда A предшествует B в порядке модификации M, который определен ниже.
Этот разговор также поддерживает идею о том, чтоприведенный выше код не распространяется на гонки.https://www.youtube.com/watch?v=KeLBd2EJLOU&feature=youtu.be&t=1h9m30s
Мне кажется, что является неделимым порядком атомных операций, но у нас нет никаких гарантий, что это за порядок.Таким образом, все приращения должны происходить «один перед другим» без гонки, которую я описал выше.
Но тогда некоторые вещи потенциально могут указывать в другом направлении:
Реализации должны делать атомарныемагазины, видимые для атомных нагрузок, в течение разумного промежутка времени.
Коллега сообщил мне, что в выступлении Саттера есть известные ошибки.Хотя я до сих пор не нашел никаких источников для этого.
Несколько членов сообщества C ++ умнее, чем я предполагал, что расслабленное атомарное добавление может быть буферизовано так, чтобы последующее расслабленное атомарное добавление могло читать и обрабатыватьустаревшее значение.