【发布时间】:2016-07-22 07:51:13
【问题描述】:
我写这篇文章是为了参考Atomic store. Structures
@Peter Cordes 说:
锁定是什么意思?特别是,我知道 lock 是一个前缀 这确保了“前缀”指令的原子性。
锁定为 自旋锁/互斥锁,不是锁前缀。锁定前缀仅适用于 读-修改-写指令;没有锁 mov [mem], eax 可做 一个原子未对齐的存储或其他东西。锁定总线周期总是 读取-修改-写入,如 Intel 在 cmpxchg 的文档中所述。所以 lock mov 存储也会产生一个负载,它有不同的 如果您在内存映射 I/O 上使用它,则语义。 (一个读可以触发边 效果)。
好的,我理解得很好。但是,我不明白为什么它会被原子地复制(存储)。它可能是自旋锁而不是互斥锁,但情况是一样的。我同意,关键部分是安全的。但是对于原子执行并不确定。
我添加一个例子来解释我的意思:
struct S{int a, b, c, d, e;};
std::mutex mut; // global
S s = {0}; // global
//From what I understand atomic store could look like:
store(const S& src){
mut.lock();
S* dst = this->getPointerOfRawStructure(); // pseudocode
dst->a = src.a;
dst->b = src.b;
dst->c = src.c;
dst->d = src.d;
dst->e = src.e;
// I know that we can copy it in a better (faster) way.
mut.unlock();
});
现在,让 thread1 去做:
std::atomic<S> as;
as.store(s);
现在,互斥锁是免费的,所以 thread1 成功调用了 store。
让 thread2 做类似的事情;
S* ptr = &s; // address of global variable s declared before.
int ee = s->e;
并且,假设thread1 执行了
dst->a = src.a;
dst->b = src.b;
dst->c = src.c;
现在thread2 执行了:
int ee = s->e;
Thread2 看到 s->e 的旧值,尽管 as.store() 是首先启动的,它应该以原子方式执行。 (另一个线程看不到半写的变量,实际上它看到了)。
所以,我仍然不明白如何使用锁(自旋锁/互斥锁)确保原子性。
【问题讨论】:
标签: multithreading c++11 x86