一元增量运算符的原子行为



在某个地方我读到一元运算符本质上是原子运算符,因此它们可以在多线程环境中原样使用。为了证实这一点,我写了两个单独的程序,在中

  1. 我使用了一个变量x,并使用一元运算符++x递增
  2. 我使用了一个变量x,并使用x=x+1递增

我比较了两个程序的反汇编,没有发现任何差异。请提供您对此的意见。

在某个地方我读到一元运算符本质上是原子运算符,因此它们可以在多线程环境中原样使用。

那个来源完全错误。您需要使用std::atomic(或等效的C)来实现原子性–一元运算并不特殊。


我比较了两个程序的反汇编,没有发现的差异

这并不意味着生成的操作是原子操作。没有区别,因为任何像样的编译器都会将x=x+1++x优化到同一个程序集中(假设是内置类型)。

在编写跨平台C++时,使用std::atomic<>时只有原子行为。

的确,在某些平台上,比如英特尔64位,处理器保证inc是原子的。但是,请不要编写依赖于此的代码!作为您未来的调试器,我想知道哪些数据是要在线程上共享的,哪些不是。

使用std::atomic<int>可能需要更多的工作来编写,但是,它确实保证了一切都是原子性的(在每个平台上),要么回到平台需求(std::atomic::is_lock_free),要么显式地在访问周围加锁。它还插入了保护程序,以确保其他处理器内核的缓存无效(如果平台需要这样做)。

在英特尔64位的实践中,这应该会给您提供相同的程序集,如果没有,请在编译器上记录错误。

同时,一些使用int的操作可能不是原子操作(运算符*=),std::atomic根本不包含这些操作,需要正确处理这些操作。

附带说明:++xx = x+1是不同的操作,它们可能被优化为相同的程序集。考虑到非原子平台需求,第二个问题突然出现,需要数天时间才能解决。

一元运算符必然是原子运算符的断言纯属无稽之谈。

例如,++x需要对x进行读写,这样就有可能出现数据竞争。

++x编译为与x = x + 1相同的代码这一事实并不相关。

如果希望避免数据竞争,则使用原子类型,如果没有合适的原子类型,则使用互斥单元。为避免疑义,int不一定是原子类型。

在某个地方我读到一元运算符本质上是原子的,因此它们可以在多线程环境中按原样使用。

这是错误的。例如,x++需要x的加载、x的添加和存储。这些指令本质上不是原子指令。

不正确。即使是这样,什么原因会https://en.cppreference.com/w/cpp/atomic/atomic#Type_aliases然后呢?

我认为他们的意思可能是,对这样的运算的计算通常是非常微小的,因此很可能永远不会有竞争条件,这在实时代码中最为真实,因为你不会同时在4个循环中计算x++。

您没有指定x的类型。

  1. 如果x是32位整数,而平台是16或8位,则"x++"运算肯定会进行多次操作
  2. x甚至可能不是基本类型,x可能是Class的一个实例,其中运算符++所做的事情要比递增整数复杂得多

操作stronglr的原子性取决于目标系统。在像RISC微控制器这样的RMW系统上,一元操作可能不是原子操作。

这个问题没有单一的通用答案。

您对生成的代码进行假设,如果只生成一条指令,是的,它将是原子的,否则不是。

在您的情况下,这假设目标处理器有指令inc <address>,编译器将生成它

一元运算符的原子行为

在C中,修复前/修复后的++不是一元运算符,如& * + - ~ !。而是一元表达式的一部分。因此问题标题与正文不一致。

即使是像+这样的一元运算符也不是原子运算符,因为对对象的访问(想想long long)需要读取多个操作代码。

相关内容

  • 没有找到相关文章

最新更新