【发布时间】:2016-04-13 19:34:47
【问题描述】:
假设我们有一个具有以下实现的 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;
当ct->foo 被打印时,我能保证得到3 吗? mtx 为指针本身提供了happens-before 语义,但我不确定这对ComplexType 的内存有什么影响。如果得到保证,是否意味着每个互斥锁 (std::lock_guard<std::mutex> lck(mtx);) 都会强制对任何已修改的内存位置进行完全缓存失效,直到独立内核的内存层次结构合并的地方?
【问题讨论】:
-
呃,如果线程 2 在线程 1 之前获得互斥锁怎么办?
-
任何写入内存的数据都会导致缓存行失效,但我不知道你会说什么“强制完全缓存失效”
-
@Brian - 是的,正确 - 假设顺序如上所示。
-
这个对较早问题的回答表明,是的,如果硬件需要,互斥函数会发出内存屏障指令:stackoverflow.com/a/24143387/1401351
-
ct->foo = 3happens-beforestd::cout << ct->foo,因此后者可以保证观察到前者的副作用。分配在q.push(ct)之前排序,在q.pop()之前发生,在对ct->foo的读取访问之前排序。 “happens-before”关系在“happens-before”和“sequenced-before”边上是可传递封闭的。 Cashes 和 cores 是不相关的实现细节。
标签: c++ multithreading c++11 caching mutex