简体   繁体   English

原子变量还需要锁定读取-修改-存储操作吗?

[英]atomic variable also require lock on read-modify-store operation?

I know atomic variable is lock-free!!我知道原子变量是无锁的!!
It doesn't lock thread, but I have one question..它不会锁定线程,但我有一个问题..
Read-Modify-Store operation like std::atomic::fetch_add is also executed atomically???像 std::atomic::fetch_add 这样的 Read-Modify-Store 操作也是原子执行的???
I think this operation isn't just a one instruction.我认为这个操作不仅仅是一个指令。
It need multiple cycle... So If i doesn't lock memory bus ( Actually i don't know if mutex locking contain memory bus lock), Other thread can make memory operation between Read and Store.它需要多个周期......所以如果我不锁定 memory 总线(实际上我不知道互斥锁是否包含 memory 总线锁定),其他线程可以在读取和存储操作之间进行 memory 操作。
So I think it require locking even if atomic variable...所以我认为即使原子变量也需要锁定......

Am i knowing well???我是不是很清楚???

You konwing is right in in earlyer x86 architecture. You konwing 就在早期的 x86 架构中。

In the x86 architecture, the instruction prefix LOCK is provided.Atomic variables depend on this directive.Early a LOCK is implemented by locking a bus to prevent memory access from other CPU cores.在 x86 架构中,提供了指令前缀 LOCK。原子变量依赖于该指令。早期的 LOCK 是通过锁定总线来实现的,以防止 memory 从其他 CPU 内核访问。 As you can imagine, this implementation is very inefficient可以想象,这种实现效率非常低

Most x86 processors support the hardware implementation of CAS, which ensures the correctness of atomic operation in multi-processor and multi-core systems.大多数x86处理器都支持CAS的硬件实现,保证了多处理器多核系统中原子操作的正确性。 The implementation of CAS also does not lock the bus and only blocks access by other CPUs to the cache blocks that check the associated memory. CAS 的实现也不会锁定总线,只会阻止其他 CPU 对检查相关 memory 的缓存块的访问。 let show you code.让你看看代码。 example code is:示例代码是:

#include <iostream>
#include <thread>
#include <atomic>
 
std::atomic<long long> data;
void do_work()
{
    data.fetch_add(1, std::memory_order_relaxed);
}
 
int main()
{
    std::thread th1(do_work);
    std::thread th2(do_work);
    std::thread th3(do_work);
    std::thread th4(do_work);
    std::thread th5(do_work);
 
    th1.join();
    th2.join();
    th3.join();
    th4.join();
    th5.join();
 
    std::cout << "Result:" << data << '\n';
}

Convert the above code into instructions.将上述代码转换为指令。 In gcc 8 do_work function translated into在 gcc 8 do_work function 翻译成

        push    rbp
        mov     rbp, rsp
        mov     QWORD PTR [rbp-8], 1
        mov     DWORD PTR [rbp-12], 0
        mov     rax, QWORD PTR [rbp-8]
        mov     edx, OFFSET FLAT:data
        lock xadd       QWORD PTR [rdx], rax
        nop
        pop     rbp
        ret

use lock xadd to ensure atomic operator.使用lock xadd来确保原子操作符。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM