Atomicity in C++ : Myth or Reality

依然范特西╮ 提交于 2019-11-27 03:20:53

This recommendation is architecture-specific. It is true for x86 & x86_64 (in a low-level programming). You should also check that compiler don't reorder your code. You can use "compiler memory barrier" for that.

Low-level atomic read and writes for x86 is described in Intel Reference manuals "The Intel® 64 and IA-32 Architectures Software Developer’s Manual" Volume 3A ( http://www.intel.com/Assets/PDF/manual/253668.pdf) , section 8.1.1

8.1.1 Guaranteed Atomic Operations

The Intel486 processor (and newer processors since) guarantees that the following basic memory operations will always be carried out atomically:

  • Reading or writing a byte
  • Reading or writing a word aligned on a 16-bit boundary
  • Reading or writing a doubleword aligned on a 32-bit boundary

The Pentium processor (and newer processors since) guarantees that the following additional memory operations will always be carried out atomically:

  • Reading or writing a quadword aligned on a 64-bit boundary
  • 16-bit accesses to uncached memory locations that fit within a 32-bit data bus

The P6 family processors (and newer processors since) guarantee that the following additional memory operation will always be carried out atomically:

  • Unaligned 16-, 32-, and 64-bit accesses to cached memory that fit within a cache line

This document also have more description of atomically for newer processors like Core2. Not all unaligned operations will be atomic.

Other intel manual recommends this white paper:

http://software.intel.com/en-us/articles/developing-multithreaded-applications-a-platform-consistent-approach/

I think you are misinterpreting the quote.

Atomicity can be guaranteed on a given architecture, using specific instructions (proper to this architecture). The MSDN article explains that read and writes on C++ built-in types can be expected to be atomic on x86 architecture.

However the C++ standard does not presume what the architecture is, therefore the Standard cannot make such guarantees. Indeed C++ is used in embedded software where the hardware support is much more limited.

C++0x defines the std::atomic template class, which allows to turn reads and writes into atomic operations, whatever the type. The compiler will select the best way to obtain atomicity based on the type characteristics and the architecture targeted in a standard compliant manner.

The new standard also defines a whole lot of operations similar to MSVC InterlockExchange that is also compiled to the fastest (yet safe) available primitives offered by the hardware.

The c++ standard does not guarantee atomic behaviour. In practice however simple load and store operations will be atomic, as the article states.

If you need atomicity, better to be explicit about it and use some sort of lock though.

*counter = 0; // this is atomic on most platforms
*counter++;   // this is NOT atomic on most platforms

Be very careful when relying on the atomicity of simple word size operations because things might behave differently from what you expect. On multicore architectures, you might witness out of order reads and writes. This will then require memory barriers to prevent. (more details here).

Bottom line for an application developer is either use primitives that the OS guarantees will be atomic or use appropriate locks.

IMO, the article incorporates some assumptions about the underlying architecture. As C++ has only some minimalistic requirements on the architecture, no guarantees for example about atomicity can be given in the standard. For example a byte has to be at least 8 bits, but you could have an architecture where a byte is 9 bits, but an int 16... theoretically.

So when the compiler is specific for x86 architecutre, the specific features can be used.

NB: structs are usually aligned by default to a native word boundary. you can disable that by #pragma statements, so your padding fills are not required

I think what they are trying to get accross, is that data types implemented natively by the hardware, are updated within the hardware such that reading from another thread will never give you a 'partially' updated value.

Consider a 32 bit integer on a 32+ bit machine. It is written or read completely in 1 instruction cycle, whereas data types of larger sizes, say a 64 bit int on a 32 bit machine will require more cycles, hence theoretically the thread writing them could be interrupted in between those cycles ergo the value is not in a valid state.

No useing string would not make it atomic, as string is a higher level construct and not implemented in the hardware. Edit: As per your comment on what you (didnt) mean about changing to string, it should not make any difference to fields declared after, as mentioned in another answer the compiler will align fields by default.

The reason it is not in the standard is that, as stated in the article this is about how modern processors implement the instructions. Your standard C/C++ code should work exactly the same on a 16 or 64 bit machine (just with performance difference), however if you assume you will only execute on a 64 bit machine, then anything 64bits or smaller is atomic. (SSE etc type aside)

I think atomicity as it is referred in the article has little practical usage. This means that you'll read/write valid value but probably outdated. So reading an int, you'll read it completely, not 2 bytes from an old value and other 2 bytes from a new value currently being written by another thread.

What is important for shared memory is memory barriers. And they are guarantied by synchronization primitives such as C++0x atomic types, mutexes etc.

I do not think changing char Name[5] to std::string Name will make a difference if you are using it only for individual character assignments, since the index operator will return a direct reference to the underlying character. A full string assignment is not atomic (and you can't do it with a char array, so I'm guessing you weren't thinking of using it this way anyways).

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!