简体   繁体   English

使用非原子布尔值而不使用互斥体来控制跨线程的控制流是否安全?

[英]Is it safe to use a non-atomic boolean without a mutex for control flow across threads?

There are a number of related questions, but this question is arguably more specific. 有许多相关的问题,但这个问题可以说更具体。

Consider the following sample program, note that the bool is just an ordinary bool . 考虑以下示例程序,请注意bool只是一个普通的bool

When I run it, it achieves the desired effect: after the user presses Enter , hello world will cease to print. 当我运行它时,它达到了预期的效果:用户按Enterhello world将停止打印。

If I require only that bar2() eventually starts returning immediately after run is to false , is the logic below guaranteed to be safe by the standard? 如果我只要求bar2() 最终开始返回后,立即runfalse ,低于保证逻辑的标准是安全的?

#include <thread>
#include <mutex>
#include <unistd.h>


bool run = true;

void bar2() {
    // Is this check safe without a lock?
    if (!run) return;
    printf("hello world\n");
    fflush(stdout);
}
void bar() {
    while (true) {
        bar2();
        sleep(1);
    }
}

int main(){
    std::thread(bar).detach();
    getchar();
    run = false;
    // Prevent main from exiting.
    getchar();
}

There is no guarantee by the standard that without synchronization or ordering guarantees given by eg std::atomic the other thread will ever see the write to run . 标准不保证没有同步或由std::atomic给出的排序保证,其他线程将看到写入run

As a matter of fact the compiler would be perfectly fine to only check once that write is true and since the thread itself never writes to it cache the value without ever reloading it. 事实上,编译器完全可以只检查一次write是否为真,并且因为线程本身从不写入它而不会重新加载它来缓存值。 Now practically speaking with all the c library calls going on the compiler generally cannot know that none of functions writes to run and under x86 you don't have to worry about not seeing updates from other processors to memory, so it will in practice work (and even under other architectures a context switch would probably resolve the problem). 现在几乎可以说,编译器上的所有c库调用通常都不知道没有函数写入run而在x86下你不必担心没有看到从其他处理器到内存的更新,所以它在实际工作中(甚至在其他架构下,上下文切换可能会解决问题)。

But if you're talking purely from the standard's point of view? 但是,如果你纯粹从标准的角度谈论? No guarantees whatsoever. 没有任何保证。

It is certainly the case that the standard makes no guarantees of how this code will behave. 当然,标准不保证此代码的行为方式。 The testing and setting of the run variable are not properly sequenced. run变量的测试和设置未正确排序。 As a consequence, relying on the order of setting and testing constitutes undefined behaviour. 因此,依赖于设置和测试的顺序构成了未定义的行为。

The question of what a "real world" compiler will actually do is less easy. “真实世界”编译器实际上会做什么的问题不那么容易。 There are several things a compiler could reasonably do which would cause this program to fail. 编译器可以合理地做一些会导致该程序失败的事情。 It could: 它可能:

  1. Detect the UB and institute its own implentation-specific course of action, which might work as you wanted, or not. 检测UB并制定自己的特定于实施的行动方案,这可能会按您的意愿行事。 At least if you test it, you will find out which. 至少如果你测试它,你会发现哪个。
  2. Make the assumption that UB has not occurred, and delete the if(!run) test from the program, since without the UB it can never have any effect. 假设没有发生UB,并从程序中删除if(!run)测试,因为没有UB它永远不会有任何影响。
  3. Observe that the run variable is never tested after it was set, and delete the run=false , since it can never have any effect. 观察run变量在设置后从未进行过测试,并删除run=false ,因为它永远不会产生任何影响。 [This may involve assuming no UB.] [这可能涉及假设没有UB。]

If it was my choice, I wouldn't rely on this code. 如果这是我的选择,我不会依赖这个代码。 I would use the capabilities provided by the standard and write conforming behaviour. 我会使用标准提供的功能并编写符合规范的行为。

yes, it is completely safe. 是的,这是完全安全的。 most processors have 32 bit pipelines. 大多数处理器都有32位流水线。

暂无
暂无

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

相关问题 在不锁定的情况下在不同线程中读取(仅)相同的非原子变量是否安全? - Is it safe to read(only) the same non-atomic variable in different threads without locking? 是否安全地解除引用不同线程中原子对象的READ ONLY非原子指针? - Is dereferencing a READ ONLY non-atomic pointer to an atomic object in different threads safe? 同时使用非原子和原子操作 - Use non-atomic and atomic operations at the same time 在C / C ++中,使用布尔运算符短路控制流而不使用计算的布尔值是否安全? - In C/C++ is it safe to use boolean operator short circuit for control flow without using computed boolean value? 非原子&lt;&gt; 指针上的原子操作能否比原子&lt;&gt; 更安全且更快? - Can atomic operations on a non-atomic<> pointer be safe and faster than atomic<>? 我可以使用std :: atomic而不是std :: mutex在C ++中跨线程共享变量吗? - Can I safelly share a variable across threads in C++ using only std::atomic without std::mutex? 可以使用std :: atomic内存屏障在线程之间传输非原子数据吗? - Can std::atomic memory barriers be used to transfer non-atomic data between threads? 通过联合非原子访问原子 - Non-atomic access to atomic through a union 非原子对象在所有线程中都具有相同的修改顺序吗? (没有数据竞赛) - Do non-atomic objects have same modification order in all threads? (in absence of data races) 是否有 function 以原子方式加载非原子值? - Is there a function to load a non-atomic value atomically?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM