简体   繁体   English

C ++无锁线程同步

[英]C++ lock-free thread synchronization

I have following code: 我有以下代码:

bool sync=false;
int* ptr=NULL;
std::thread t([&](){
    do_a(); // long-time operation
    while(!sync){
        std::atomic_thread_fence(std::memory_order_acquire);
    }
    do_b(ptr);
});
int val=do_c();  //long-time operation
ptr=&val;
sync=true;
std::atomic_thread_fence(std::memory_order_release);
....

But whet I start this on multiprocessor computer, it sometimes happen, that do_b() is started with null pointer. 但是当我在多处理器计算机上启动它时,有时会发生do_b()从空指针开始的情况。 Indon't uneerstand well this behaviour. 不能很好地理解这种行为。 Does compiler do some optimalizations? 编译器会做一些优化吗? Or do I use fences wrong? 还是我用栅栏错了? Does these fences ensure synchronization of data between threads? 这些栅栏是否确保线程之间的数据同步?

Thank you for your tihe and help. 谢谢您的帮助。

Your program tries to write the two memory locations (ptr, sync) in that order; 您的程序尝试按该顺序写入两个存储位置(ptr,sync)。 but you haven't told your compiler and or cpu that this is necessary. 但是您还没有告诉编译器和/或CPU这是必须的。 Your compiler is free to re-arrange the order of memory writes to suit its goals (winning meaningless benchmarks). 您的编译器可以自由地重新安排内存写入的顺序,以适应其目标(赢得毫无意义的基准测试)。 Your cpu is free to re-arrange memory writes to suit its goals (reduced bus contention, meaningless benchmarks). 您的cpu可以自由地重新安排内存写入以适合其目标(减少总线争用,无意义的基准测试)。

So, first you should tell your compiler that it is important that it implement the order you desire. 因此,首先您应该告诉编译器,实现所需的顺序很重要。 You can accomplish this with the std::atomic, or possibly volatile directives(*). 您可以使用std :: atomic或可能是volatile指令(*)来完成此操作。

Secondly, you need to tell your cpu that you are depending upon the visible ordering of these stores. 其次,您需要告诉您的CPU,您所依赖的是这些商店的可见顺序。 In a single cpu, the program order (above) and visible order are the same. 在单个cpu中,程序顺序(上方)和可见顺序相同。 In multiple cpus, they not only aren't necessarily the same, but can vary with current and past system activity. 在多个CPU中,它们不仅不一定相同,而且会随当前和过去的系统活动而变化。 Thus @DanielLangr's comment about the fence location. 因此@DanielLangr对围栏位置的评论。 The fence informs the cpu that all stores preceding the fence must be visible before any stores following the fence. 防护栏通知CPU,在防护栏之后的任何商店之前,必须先看到防护栏之前的所有商店。

(*) Benchmark-focussed compiler writers have managed to reduce volatile to near meaninglessness, demonstrating the contempt compiler writers hold for their actual customers. (*)以基准为重点的编译器编写者已设法将波动降低到几乎毫无意义,这表明了编译器编写者对实际客户的鄙视。 Oddly, the 'write those bits in machine language' has proved to be more maintainable than relying on the artifacts of 'de jour' standards writers. 奇怪的是,事实证明,“依靠机器语言写那些位”比依靠“ de jour”标准编写者的工件更容易维护。 The advent of 'smart linkers' may finally neuter systems programming languages in a way that 30 years of standards committees failed to. “智能链接器”的出现最终可能会以30年的标准委员会未能采用的方式来中立系统编程语言。

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

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