繁体   English   中英

一元增量算子的原子行为

[英]Atomic behavior of unary increment operators

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

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

我比较了两个程序的反汇编,发现没有区别。 请提供您的意见。

在某处我读到一元运算符本质上是原子的,所以它们可以在多线程环境中使用。

那个来源是完全错误的。 你需要使用std::atomic (或C等价物)来实现原子性 - 一元操作并不特殊。


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

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

一元运算符必然是原子的断言是一个神话。

例如, ++x需要对x读写操作,以便开启数据竞争的机会。

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

如果您想避免数据竞争,那么如果没有适当的原子类型,则使用原子类型或互斥单元。 为避免疑义, int不一定是原子类型。

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

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

使用std::atomic<int>可能需要更多的工作来编写,但是,通过回退到平台需求( std :: atomic :: is_lock_free ),它确实保证一切都在原子上(在每个平台上)。通过明确地锁定访问。 它还插入防护装置以确保其他处理器核心的高速缓存无效(如果平台需要这样)。

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

同时,一些使用int的操作可能不是原子的(operator * =), std::atomic只是不能保存这些操作,要求你正确使用它们。

旁注: ++xx = x+1是不同的操作,它们可能针对同一个程序集进行了优化。 鉴于非原子平台要求,第二个突然是一个需要数天才能解决的错误。

在某处我读到一元运算符本质上是原子的,所以它们可以在多线程环境中使用。

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

不对。 即使这样, https://en.cppreference.com/w/cpp/atomic/atomic#Type_aliases会有什么原因呢?

我认为它们可能意味着对这种操作的计算通常是非常微小的,因此很可能永远不会有竞争条件,这在实时代码中大多数情况下都是如此,在这种代码中你不会同时计算4 for for循环中的x ++。

您没有指定x的类型。

  1. 如果x是32位整数,当平台是16位或8位时,“x ++”操作肯定会进行多次操作
  2. x甚至可能不是基本类型,x可能是Class的一个实例,其中operator ++执行更复杂的东西,然后只增加整数

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

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

你对生成的代码做了一个假设,如果只生成一条指令,那么它将是原子的,否则为no。

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

一元算子的原子行为

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

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

暂无
暂无

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

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM