【问题标题】:Storing of wider operands in an atomic way. Why did lock solve the issue?以原子方式存储更广泛的操作数。为什么锁解决了这个问题?
【发布时间】: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-&gt;e; Thread2 看到 s-&gt;e 的旧值,尽管 as.store() 是首先启动的,它应该以原子方式执行。 (另一个线程看不到半写的变量,实际上它看到了)。

所以,我仍然不明白如何使用锁(自旋锁/互斥锁)确保原子性。

【问题讨论】:

    标签: multithreading c++11 x86


    【解决方案1】:

    当然,锁和临界区不能保证绕过它们的流氓代理可以观察到什么。

    如果你在临界区做了一些操作,但是你实现了它,那么每个同意也使用它的人只能做出与临界区原子执行的想法一致的观察,因为他们自己对临界区的使用发生了在其他人使用它之前或之后,而不是在使用期间。

    如果您只是在本应受某种机制保护的事物中闲逛而不使用该机制,那么显然该机制无法阻止坏事的发生。

    如果有人决定从窗户进入,锁上门也无济于事。

    【讨论】:

    • 你说的都是真的。所以,我的论点是:现代 CPU x86 上最多 16B 可以在 意义上以 atomic 方式存储/加载/RMW 操作?那么,不可能以原子方式存储/加载更广泛的操作数吗?我说的原子是什么意思?当一个 CPU 执行任何指令时,其他 CPU(环境)能够在该操作之前或之后查看内存。结果,不可能看到半写的操作数。我说的对吗?
    • @Gilgamesz 是的,不能创建新的“纯原子”操作。有了锁等,它通常一开始就不被称为原子,但我想如果你对它进行抽象,那么在不可能的情况下以这种方式模拟它可能是合理的。
    猜你喜欢
    • 1970-01-01
    • 2021-10-14
    • 2021-01-10
    • 1970-01-01
    • 2020-04-01
    • 2021-01-17
    • 2023-03-28
    • 2012-12-18
    • 1970-01-01
    相关资源
    最近更新 更多