我可以在多线程情况下使用无锁的 char 变量吗

Yve*_*ves 3 c c++ multithreading mutex locking

正如 c/c++ 标准所说,的大小char必须是1. 据我了解,这意味着 CPU 保证char必须在一条指令中完成对 a 的任何读取或写入。

假设我们有许多线程,它们共享一个char变量:

char target = 1;

// thread a
target = 0;

// thread b
target = 1;

// thread 1
while (target == 1) {
    // do something
}

// thread 2
while (target == 1) {
    // do something
}
Run Code Online (Sandbox Code Playgroud)

总之,有两种线程:一种是设置target0or 中1,另一种是执行某些任务 if target == 1。目标是我们可以通过修改 的值来控制任务线程target

根据我的理解,我们似乎根本不需要使用mutex/lock。但是我的编码经验给了我一种强烈的感觉,我们必须mutex/lock在这种情况下使用。

我现在很困惑。mutex/lock在这种情况下我应该使用还是不使用?

你看,我可以理解为什么我们mutex/lock在其他情况下需要,例如i++. 因为i++不能只在一条指令中完成。所以可以target = 0在一条指令中完成,对吗?如果是这样,是否意味着mutex/lock在这种情况下我们不需要?

好吧,我知道我们可以使用std::atomic,所以我的问题是:既不使用mutex/lcok也不使用std::atomic.

for*_*818 5

std::atomic保证访问变量是原子的。从cppreference

std::atomic 模板的每个实例化和完全特化都定义了一个原子类型。如果一个线程写入原子对象而另一个线程从中读取,则行为是明确定义的(有关数据竞争的详细信息,请参阅内存模型)。

当 achar实际上是原子的(大小为 1 是不够的)时,则std::atomic<char>不需要额外的同步。但是,在char非原子的平台上,std::atomic<char>保证可以使用互斥锁或类似物以原子方式读取和写入。

在实践中,我希望char是原子的,但标准并不能保证这一点。

还要考虑诸如+=读取写入值之类的操作,因此单独的原子读取和写入不足以安全地调用+=,而std::atomic<T>具有适当的operator+=.

TL; 博士

我现在很困惑。在这种情况下我应该使用互斥锁/锁吗?

让别人为你做决定。当你想要一些原子性的东西时,std::atomic<something>除非你想要对同步进行细粒度控制,否则使用 a 。