C++ 是x++;;线程安全?

C++ 是x++;;线程安全?,c++,multithreading,atomicity,C++,Multithreading,Atomicity,如果我在一个线程中更新一个变量,如下所示: receiveCounter++ 然后从另一个线程中,我只读取这个变量并将其值写入GUI 安全吗?或者,这个指令会在中间被中断,所以当接收方的值被另一个线程读取时是错误的吗?它一定是正确的,因为++不是原子的,它是几个指令 我不关心同步读写,它只需要递增,然后在GUI中更新,但这不必直接在彼此之后发生 我关心的是这个值不能是错误的。类似于在中间被中断的++操作,因此读取值完全关闭。 是否需要锁定此变量?我真的不想,因为它是更新非常频繁。我想,我可以通过

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

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

安全吗?或者,这个指令会在中间被中断,所以当接收方的值被另一个线程读取时是错误的吗?它一定是正确的,因为++不是原子的,它是几个指令

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

我关心的是这个值不能是错误的。类似于在中间被中断的++操作,因此读取值完全关闭。

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

但无论如何,我对上面的问题很感兴趣。

简单的回答:不

因为
i++
i=i+1相同,它包含加载、数学运算和保存值。所以它通常不是原子的。

但是,实际执行的操作取决于CPU的指令集,可能是原子的,具体取决于CPU体系结构。但是默认值仍然不是原子的。

一般来说,它不是线程安全的,因为++操作符包含一个读操作和一个写操作,这两个操作对不是原子的,可以在其间中断

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

(编辑)


至于读写操作本身,只要您不是在64位模式下,它们就应该是原子的,因此,如果您不关心其他线程的值被1弄错,那么您的情况就可以了。

++相当于
i=i+1


++不是
原子操作
,因此它的
不是线程安全的。只有原语变量的读写(long和double除外)是原子的,因此是线程安全的

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


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

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

虽然这听起来像是原子指令,但因为它是一条指令,所以它仍然不是。x86/x64指令集与执行引擎的实际实现方式无关。它像“微操作”一样执行RISC,INC指令被转换为多个微操作。可以使用指令上的锁定前缀使其成为原子。但是编译器不会发出它,除非他们知道需要原子更新


因此,您需要明确地说明这一点。原子标准加法是一种很好的方法。您的操作系统或编译器将为其提供内部函数,通常命名为“Interlocked”或“内置”

如果一个线程更改变量中的值,而另一个线程读取该值,并且程序不同步访问,则会出现数据争用,并且程序的行为未定义。将
receiveCounter
的类型更改为
std::atomic
(假设它首先是
int

您所说的是什么语言?这可能很有用:不仅如此,有时如果结果不正确也可以。例如,如果GUI线程正在轮询变量,那么在几分之一秒的时间内出现错误的值是可以的。在进度计数器/进度条等每秒钟在计时器上更新一次的情况下,所看到的值总是会在某种程度上过时,所以为什么要为偶尔的打嗝而烦恼呢?在许多处理器上,++最终都会变成一条指令。答案正确,推理错误。它可以在某些处理器上的单个指令中实现。但是,由于C++中没有指定处理器,因为操作在C++标准中没有被指定为原子,所以它不是线程安全的。不,代码> i++< /> >不等于<代码> i= i+1 。@ EJP,请您在上面的注释中再详细说明一下吗?“只有原始变量(除了长和double)之外的原子的读写是原子的”。C++11甚至不能保证这一点。如果你想要原子性和线程安全,你使用的是
std::atomic
,没有捷径。我理解这个问题,因为只有读部分和写部分需要是原子的。不是整个读修改写。这不应该更像是一个对齐和数据大小问题吗。