Я попытался найти подробности об этом, я даже прочитал стандарт по мьютексам и атомизации... но все же я не мог понять возможности видимости модели памяти С++ 11. Из того, что я понимаю, очень важной особенностью взаимного исключения мьютекса BESIDE является обеспечение видимости. Ака недостаточно, чтобы только один поток за время увеличивал счетчик, важно, чтобы поток увеличил счетчик, который был сохранен потоком, который последний раз использовал мьютекс (я действительно не знаю, почему люди больше не упоминают об этом больше при обсуждении мьютексы, может быть, у меня были плохие учителя:)). Поэтому из того, что я могу сказать, атомный не обеспечивает немедленную видимость: (от человека, который поддерживает boost:: thread и реализовал библиотеку С++ 11 thread и mutex):
Забор с memory_order_seq_cst не обеспечивает немедленного видимость для других потоков (а также инструкция MFENCE). Ограничения порядка памяти С++ 0x - это то, что: порядок ограничения. Операции memory_order_seq_cst образуют общий порядок, но нет никаких ограничений на то, что этот порядок, за исключением того, что он должен согласовываться всеми потоками, и он не должен нарушать другие заказы ограничения. В частности, потоки могут продолжать видеть "устаревшие" значения в течение некоторого времени, если они видят значения в порядке, согласованном с ограничения.
И я в порядке с этим. Но проблема в том, что мне трудно понять, какие конструкции С++ 11 относительно атома являются "глобальными" и которые обеспечивают согласованность только для атомных переменных. В частности, у меня есть понимание того, какие (если таковые имеются) из следующих порядков памяти гарантируют, что будет забор памяти до и после загрузки и хранения: http://www.stdthread.co.uk/doc/headers/atomic/memory_order.html
Из того, что я могу сказать, std:: memory_order_seq_cst вставляет мембранный барьер, в то время как другие только обеспечивают упорядочение операций в определенной ячейке памяти.
Итак, кто-нибудь может это понять, я полагаю, что многие люди собираются делать ужасные ошибки, используя std:: atomic, esp, если они не используют по умолчанию (std:: memory_order_seq_cst порядок памяти)
2. Если я прав, это означает, что вторая строка redundand в этом коде:
atomicVar.store(42);
std::atomic_thread_fence(std::memory_order_seq_cst);
3. do std:: atomic_thread_fences имеют те же требования, что и мьютексы, в том смысле, что для обеспечения согласованности seq на неатомических vars нужно делать std:: atomic_thread_fence (std:: memory_order_seq_cst);
перед загрузкой и станд:: atomic_thread_fence (станд:: memory_order_seq_cst);
после магазинов?
4. Является ли
{
regularSum+=atomicVar.load();
regularVar1++;
regularVar2++;
}
//...
{
regularVar1++;
regularVar2++;
atomicVar.store(74656);
}
эквивалентно
std::mutex mtx;
{
std::unique_lock<std::mutex> ul(mtx);
sum+=nowRegularVar;
regularVar++;
regularVar2++;
}
//..
{
std::unique_lock<std::mutex> ul(mtx);
regularVar1++;
regularVar2++;
nowRegularVar=(74656);
}
Я думаю, что нет, но я хотел бы быть уверен.
EDIT:
5.
Может утверждать огонь?
Существуют только два потока.
atomic<int*> p=nullptr;
первый поток пишет
{
nonatomic_p=(int*) malloc(16*1024*sizeof(int));
for(int i=0;i<16*1024;++i)
nonatomic_p[i]=42;
p=nonatomic;
}
вторая строка читает
{
while (p==nullptr)
{
}
assert(p[1234]==42);//1234-random idx in array
}