我试着寻找这方面的细节,我什至阅读了关于互斥锁和原子的标准......但我仍然无法理解 C++11 内存模型可见性保证。据我了解,互斥互斥的非常重要的特性是确保可见性。也就是每次只有一个线程增加计数器是不够的,重要的是线程增加最后使用互斥锁的线程存储的计数器(我真的不知道为什么人们在讨论时不提这个互斥体,也许我有不好的老师:))。因此,据我所知, atomic 不会强制立即可见:(来自维护 boost::thread 并已实现 c++11 线程和互斥库的人):
带有 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 插入了内存屏障,而其他只强制对某些内存位置的操作进行排序。
所以有人可以澄清一下吗,我想很多人会使用 std::atomic 制造可怕的错误,尤其是如果他们不使用默认值 (std::memory_order_seq_cst 内存排序)
2. 如果我是对的,这是否意味着此代码中的第二行是多余的:
atomicVar.store(42);
std::atomic_thread_fence(std::memory_order_seq_cst);
3. 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
}