简体   繁体   English

一元增量算子的原子行为

[英]Atomic behavior of unary increment operators

Somewhere I read that unary operators are atomic by nature and so they can be used as it is in multi threaded environment. 在某处我读到一元运算符本质上是原子的,所以它们可以在多线程环境中使用。 To confirm the same, I wrote two separate programs where in 为了证实这一点,我写了两个单独的程序

  1. I used a variable x and incremented using unary operator ++x 我使用变量x并使用一元运算符++ x递增
  2. I used a variable x and incremented using x=x+1 我使用变量x并使用x = x + 1递增

I compared the disassembly of both programs and found no difference. 我比较了两个程序的反汇编,发现没有区别。 Please provide your inputs on this. 请提供您的意见。

Somewhere I read that unary operators are atomic by nature and so they can be used as it is in multi threaded environment. 在某处我读到一元运算符本质上是原子的,所以它们可以在多线程环境中使用。

That source is completely wrong. 那个来源是完全错误的。 You need to use std::atomic (or the C equivalent) to achieve atomicity – unary operations are not special. 你需要使用std::atomic (或C等价物)来实现原子性 - 一元操作并不特殊。


I compared the disassembly of both programs and found no difference 我比较了两个程序的反汇编,发现没有区别

That doesn't mean that the generated operations are atomic. 这并不意味着生成的操作是原子的。 There is no difference as any decent compiler will optimize x=x+1 and ++x into the same assembly (assuming built-in types). 没有任何区别,因为任何体面的编译器都会将x=x+1++x优化到同一个程序集中(假设内置类型)。

The assertion that a unary operator is necessarily atomic is a myth. 一元运算符必然是原子的断言是一个神话。

For example, ++x requires a read and write to x so that opens up the chance of a data race. 例如, ++x需要对x读写操作,以便开启数据竞争的机会。

The fact that ++x compiles to the same code as x = x + 1 is not relevant. ++x编译为与x = x + 1相同的代码这一事实并不重要。

If you want to avoid data races then use atomic types, or mutual exclusion units if an appropriate atomic type is not available. 如果您想避免数据竞争,那么如果没有适当的原子类型,则使用原子类型或互斥单元。 For the avoidance of doubt, int is not necessarily an atomic type. 为避免疑义, int不一定是原子类型。

When writing cross platform C++, you only have atomic behavior when using std::atomic<> . 编写跨平台C ++时,使用std::atomic<>时只有原子行为。

It is true that on certain platforms, like Intel 64bit, the processor guarantees that inc is atomic. 确实,在某些平台上,如Intel 64bit,处理器保证inc是原子的。 However, please don't write code that depends on this! 但是,请不要编写依赖于此的代码! As your future debugger, I would like to know which data is intended to be shared over threads and which isn't. 作为您未来的调试器,我想知道哪些数据是通过线程共享的,哪些不是。

Using std::atomic<int> might be a bit more work to write, however, it does guarantee that everything behaves atomically (on every platform) by either falling back to the platform requirements ( std::atomic::is_lock_free ), or by explicitly putting a lock around the access. 使用std::atomic<int>可能需要更多的工作来编写,但是,通过回退到平台需求( std :: atomic :: is_lock_free ),它确实保证一切都在原子上(在每个平台上)。通过明确地锁定访问。 It as well insert guards in order to make sure that the caches of the other processor cores are invalidated (if the platform requires this). 它还插入防护装置以确保其他处理器核心的高速缓存无效(如果平台需要这样)。

In practice for Intel 64bit, this should give you the same assembly, if not, log a bug on your compiler. 在英特尔64位的实践中,这应该给你相同的程序集,如果没有,记录你的编译器的错误。

At the same time, some operations with ints might not be atomic (operator*=), std::atomic simply doesn't hold those operations, requiring you to correctly work with those. 同时,一些使用int的操作可能不是原子的(operator * =), std::atomic只是不能保存这些操作,要求你正确使用它们。

On a side note: ++x and x = x+1 are different operations, they might be optimized to the same assembly. 旁注: ++xx = x+1是不同的操作,它们可能针对同一个程序集进行了优化。 Given non-atomic platform requirements, the second suddenly is a bug which takes days to solve. 鉴于非原子平台要求,第二个突然是一个需要数天才能解决的错误。

Somewhere I read that unary operators are atomic by nature and so they can be used as it is in multi threaded environment. 在某处我读到一元运算符本质上是原子的,所以它们可以在多线程环境中使用。

That's false. 那是假的。 x++ for example requires a load of x , an add and a store of x . 例如, x++需要加载x ,加载和x的存储。 Those instructions are not atomic by nature. 这些指令本质上不是原子的。

Not true. 不对。 Even if it would be, what reason would https://en.cppreference.com/w/cpp/atomic/atomic#Type_aliases then have? 即使这样, https://en.cppreference.com/w/cpp/atomic/atomic#Type_aliases会有什么原因呢?

I think what they probably meant is that a computation on such operation is usually very minute and thus high likely to never have a race condition, which is mostly true in live code where you dont calculate x++ in 4 for loops simultaneously. 我认为它们可能意味着对这种操作的计算通常是非常微小的,因此很可能永远不会有竞争条件,这在实时代码中大多数情况下都是如此,在这种代码中你不会同时计算4 for for循环中的x ++。

You didn't specify the type of x. 您没有指定x的类型。

  1. If x is 32 bit integer when platform is 16 or 8 bit, 'x++' operation will definitely will make multiple operations 如果x是32位整数,当平台是16位或8位时,“x ++”操作肯定会进行多次操作
  2. x could be even not basic type, x could be a instance of Class where operator++ does much more complicated stuff then just increment integer x甚至可能不是基本类型,x可能是Class的一个实例,其中operator ++执行更复杂的东西,然后只增加整数

The atomicity of the of the operation stronglr depends on the target system. 操作stronglr的原子性取决于目标系统。 Unary operation might not be atomic on RMW systems like RISC micro controllers. 在RMW系统(如RISC微控制器)上,一元操作可能不是原子操作。

There is no single generic answer for this question. 这个问题没有一个通用的答案。

You make an assumption on the generated code, if only one instruction is generated yes it will be atomic, else no. 你对生成的代码做了一个假设,如果只生成一条指令,那么它将是原子的,否则为no。

In your case this supposes the target processor has the instruction inc <address> and the compiler will produce it. 在您的情况下,这假设目标处理器具有指令inc <address> ,并且编译器将生成它。

Atomic behavior of unary operators 一元算子的原子行为

In C, pre/post fix ++ are not unary-operators such as & * + - ~ ! 在C中,前/后修复++不是一元运算符,例如& * + - ~ ! . but part of a unary-expression . 但是一元表达的一部分 So the question title is inconsistent with the body. 因此问题标题与身体不一致。

Even a unary operator like + is not atomic as access to the object (think long long ) make take multiple op code reads. 即使像+这样的一元运算符也不是原子的,因为访问该对象(想想long long )可以进行多个操作码读取。

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

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