假设我们有一个SyncQueue
类,其实现如下:
class SyncQueue {
std::mutex mtx;
std::queue<std::shared_ptr<ComplexType> > m_q;
public:
void push(const std::shared_ptr<ComplexType> & ptr) {
std::lock_guard<std::mutex> lck(mtx);
m_q.push(ptr);
}
std::shared_ptr<ComplexType> pop() {
std::lock_guard<std::mutex> lck(mtx);
std::shared_ptr<ComplexType> rv(m_q.front());
m_q.pop();
return rv;
}
};
然后我们有这个使用它的代码:
SyncQueue q;
// Thread 1, Producer:
std::shared_ptr<ComplexType> ct(new ComplexType);
ct->foo = 3;
q.push(ct);
// Thread 2, Consumer:
std::shared_ptr<ComplexType> ct(q.pop());
std::cout << ct->foo << std::endl;
我确保在3
打印时获得ct->foo
? mtx
提供指针本身的语义之前发生,但我不确定是否为ComplexType
的内存说了什么。如果有保证,这是否意味着每个互斥锁(std::lock_guard<std::mutex> lck(mtx);
)强制任何已修改的内存位置的完全缓存失效,直到独立内核的内存层次结构合并为止?
答案 0 :(得分:2)
std :: mutex()符合Mutex要求(http://en.cppreference.com/w/cpp/concept/Mutex)
这里解释了在同一个互斥锁上执行m.unlock()之前的操作与此同步 锁定操作(相当于release-acquire std :: memory_order)
release-acquire(http://en.cppreference.com/w/cpp/atomic/memory_order)
发布 - 获取订购
如果标记了线程A中的原子库 memory_order_release和线程B中的原子加载来自同一个 变量标记为memory_order_acquire,所有内存写入(非原子的) 发生在原子商店之前的事情 线程A的观点,在线程B中成为可见的副作用, 也就是说,一旦原子加载完成,线程B就可以保证 看到线程A写入内存的所有内容。
同步是 仅在释放和获取相同的线程之间建立 原子变量。其他线程可以看到不同的内存顺序 访问比同步线程中的任何一个或两个。
本节中的代码示例与您的代码示例非常相似。所以应该保证线程1中的所有写操作都会在push()中的互斥锁解锁之前发生。
当然,如果&#34; ct-&gt; foo = 3&#34;没有任何特殊的棘手意义,其中实际的赋值发生在另一个线程中:))
来自cppreference的wrt cache-invalidation:
在强烈排序的系统(x86,SPARC TSO,IBM大型机)上, 发布 - 获取订购对于大多数操作是自动的。 不会为此同步发出其他CPU指令 模式,只有某些编译器优化受到影响(例如 禁止编译器将非原子存储移动到原子之外 存储 - 释放或执行早于原子的非原子加载 负载获取)。在弱有序系统(ARM,Itanium,PowerPC)上, 必须使用特殊的CPU加载或内存栅栏指令。
所以它真的取决于架构。