是x ++;线程安全的?

时间:2013-08-16 08:21:42

标签: c++ multithreading atomicity

如果我在一个线程中更新变量,如下所示: receiveCounter ++;

然后从另一个线程我只读过这个变量并将其值写入GUI。

这样安全吗?或者这个指令可能在中间被中断,所以当另一个线程读取时,receiveCounter中的值是错误的?它必须如此正确,因为++不是原子的,它是几个指令。

我不关心同步读取和写入,它只需要递增然后在GUI中更新,但这不必在彼此之后直接发生。

我关心的是价值不能错。就像++操作在中间被中断一样,读取值完全关闭。

我需要锁定此变量吗?我真的不想,因为它经常更新。我可以通过向MAIN线程发送消息并将值复制到队列(然后需要锁定但我不会在每次更新时都这样做)来解决这个问题。我想。

但无论如何我对上述问题感兴趣。

6 个答案:

答案 0 :(得分:2)

它的核心是读 - 修改 - 写操作,它们不是原子的。周围有一些处理器有专门的指令。像Intel / AMD内核一样,它们很常见,它们有INC指令。

虽然听起来像那样可能是原子的,因为它只是一条指令,但它仍然不是。与实际执行执行引擎的方式相比,x86 / x64指令集没有太多工作要做。其中执行类似RISC的“微操作”,INC指令被转换为多个微操作。 可以使用指令上的LOCK前缀成为原子。但编译器不会发出它,除非他们知道需要原子更新。

因此,你需要明确它。 C ++ 11 std :: atomic<>标准添加是一个好方法。您的操作系统或编译器将具有内在函数,通常命名为“Interlocked”或“__built_in”。

答案 1 :(得分:2)

如果一个线程更改了变量中的值而另一个线程读取了该值并且程序没有同步访问,则它具有数据争用,并且程序的行为未定义。将receiveCounter的类型更改为std::atomic<int>(假设它始于int

答案 2 :(得分:1)

++相当于i=i+1

++不是atomic operation所以它的NOT线程是安全的。只读取和写入原始变量(long和double除外)是原子的,因此是线程安全的。

答案 3 :(得分:0)

简单回答:不。

因为i++;i = i + 1;相同,它包含load,math-operation并保存值。所以至少3次操作不是原子的。

答案 4 :(得分:0)

一般来说,它是线程安全的,因为++运算符包含一个 read 和一个 write ,其中一对不是原子的,可以在两者之间中断。

然后,它可能还取决于语言/编译器/体系结构,但在典型情况下,增量操作可能不是线程安全的。

(编辑)的

至于读取操作本身,只要你不处于64位模式,它们应该是原子的,所以如果你不在乎关于错误值为1的其他线程,你的情况可能没问题。

答案 5 :(得分:0)

没有。增量操作不是原子操作,因此不是线程安全的。

在您的情况下,如果您在特定时间内不关心它的值,那么使用此操作是安全的(如果您只是从另一个线程读取此变量而不是尝试写入它)。它最终会增加receiveCounter的值,你只是对操作顺序没有任何保证。