简体   繁体   中英

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
  2. I used a variable x and incremented using 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.


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).

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.

The fact that ++x compiles to the same code as x = x + 1 is not relevant.

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.

When writing cross platform C++, you only have atomic behavior when using std::atomic<> .

It is true that on certain platforms, like Intel 64bit, the processor guarantees that inc is atomic. 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. 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.

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.

On a side note: ++x and x = x+1 are different operations, they might be optimized to the same assembly. 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 . 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?

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.

You didn't specify the type of x.

  1. If x is 32 bit integer when platform is 16 or 8 bit, 'x++' operation will definitely will make multiple operations
  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

The atomicity of the of the operation stronglr depends on the target system. Unary operation might not be atomic on RMW systems like RISC micro controllers.

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.

In your case this supposes the target processor has the instruction inc <address> and the compiler will produce it.

Atomic behavior of unary operators

In C, pre/post fix ++ are not unary-operators such as & * + - ~ ! . 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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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