Я пытался найти подробности об этом, я даже читал стандарт мьютексов и атомарности ... но все же я не мог понять гарантии видимости модели памяти C ++ 11.Из того, что я понимаю, очень важная особенность взаимного исключения мьютекса - это обеспечение видимости.Ака, недостаточно того, что только один поток за раз увеличивает счетчик, важно, чтобы поток увеличивал счетчик, который был сохранен потоком, который последний раз использовал мьютекс (я действительно не знаю, почему люди не упоминают об этом больше при обсуждениимьютексы, может у меня были плохие учителя :)).Итак, из того, что я могу сказать, atomic не обеспечивает немедленной видимости: (от человека, который поддерживает boost :: thread и реализовал c ++ 11 thread и библиотеку mutex):
Забор с memory_order_seq_cst не делаетобеспечить немедленную видимость другим потокам (и ни одна из них не делает инструкцию MFENCE).Ограничения упорядочения памяти C ++ 0x - это просто ограничения упорядочения.Операции memory_order_seq_cst формируют общий порядок, но нет никаких ограничений относительно того, что это за порядок, за исключением того, что он должен быть согласован всеми потоками и не должен нарушать другие ограничения порядка.В частности, потоки могут продолжать видеть «устаревшие» значения в течение некоторого времени, при условии, что они видят значения в порядке, совместимом с ограничениями.
И я в порядке с этим.Но проблема в том, что у меня возникают проблемы с пониманием того, что конструкции C ++ 11, относящиеся к атомарным, являются «глобальными» и которые обеспечивают согласованность только по атомарным переменным.В частности, я понимаю, какие (если таковые имеются) из следующих упорядочений памяти гарантируют, что будет ограничение памяти до и после загрузки и сохранения: http://www.stdthread.co.uk/doc/headers/atomic/memory_order.html
Из того, что я могу сказать, std :: memory_order_seq_cst вставляет memбарьер, в то время как другие только обеспечивают порядок операций в определенной области памяти.
Так что, может кто-нибудь прояснит это, я полагаю, что многие люди будут делать ужасные ошибки, используя std :: atomic, особенно если они не используют по умолчанию (std :: memory_order_seq_cst упорядочение памяти)
2.если я прав, значит ли это, что вторая строка является избыточной в этом коде:
atomicVar.store(42);
std::atomic_thread_fence(std::memory_order_seq_cst);
3.do std :: atomic_thread_fences предъявляет те же требования, что и мьютексы, в том смысле, что для обеспечения последовательности seq для неатомных переменных необходимо выполнить std :: atomic_thread_fence (std :: memory_order_seq_cst);до загрузки и std :: atomic_thread_fence (std :: 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);
}
Я думаю, что нет,но я хотел бы быть уверен.
РЕДАКТИРОВАТЬ: 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
}