Reading and writing C ++ int Atomic?

I have two threads, one of which updates int and one reads it. This is a statistical value in which the reading and writing order does not matter.

My question is: do I need to synchronize access to this multibyte value? Or, in another way, part of the record may be filled and interrupted, and then reading will occur.

For example, think of a value = 0x0000FFFF that gets an increased value of 0x00010000.

Is there a time when the value looks like 0x0001FFFF that I have to worry about? Of course, the larger the type, the more likely something like that.

I always synchronized these types of access, but I was curious what the community was thinking.

+64
c ++ multithreading synchronization
Sep 10 '08 at 14:26
source share
15 answers

At first you might think that reading and writing the machineโ€™s own size is atomic, but there are a number of problems related to cache coherency between processors / cores. Use atomic operations such as Interlocked * on Windows and the equivalent on Linux. C ++ 0x will have an โ€œatomicโ€ template to wrap them in a nice and cross-platform interface. At the moment, if you use the platform abstraction layer, this can provide these functions. ACE , see class template ACE_Atomic_Op .

+39
Sep 10 '08 at 15:37
source share
Boy, what a question. The answer to which:

Yes, no, hmm, well, it depends

It all comes down to the system architecture. On IA32, a correctly aligned address will be an atomic operation. Unexpressed entries can be atomic, it depends on the caching system used. If the memory is in the same line of the L1 cache, then it is atomic, otherwise it is not. The width of the bus between the processor and RAM can affect the atomic nature: a correctly aligned 16-bit record on 8086 was atomic, while the same record on 8088 was not because 8088 had only an 8-bit bus, while 8086 was 16- bit bus.

In addition, if you use C / C ++, do not forget to mark the general value as volatile, otherwise the optimizer will assume that the variable is never updated in one of your threads.

+53
Sep 10 '08 at 14:42
source share

IF you read / write a 4-byte value AND it is DWORD-aligned in memory AND you work in the I32 architecture, THEN the read and write are atomic.

+9
Sep 10 '08 at 14:41
source share

Yes, you need to synchronize calls. In C ++ 0x this will be data race and undefined behavior. With POSIX streams, this already works undefined.

In practice, you can get bad values โ€‹โ€‹if the data type is larger than the native word size. In addition, in another thread, the value recorded due to optimizations moving the read and / or write will never be visible.

+7
Sep 10 '08 at 14:31
source share

You have to synchronize, but on some architectures there are effective ways to do this.

It is best to use routines (possibly disguised as macros) so that you can conditionally replace implementations with platform ones.

The Linux kernel already has some code.

+3
Sep 10 '08 at 14:38
source share

On Windows, *** Exchange *** lock *** Add is guaranteed to be atomic.

+3
Sep 16 '08 at 21:46
source share

To repeat what everyone said above, the pre-C ++ 0x language cannot guarantee anything about accessing shared memory from multiple threads. Any guarantees will be up to the compiler.

+1
Sep 11 '08 at 16:07
source share

No, they are not (or at least you cannot assume that they are). Having said that, there are some tricks to do this atomically, but they are usually not portable (see Compare-and-swap ).

0
Sep 10 '08 at 2:30 p.m.
source share

I agree with many, and especially Jason . In the windows you can use InterlockedAdd and his friends.

0
Sep 10 '08 at 15:00
source share

Pay attention to the cache problem mentioned above ...

If you transfer code to a processor with a smaller register size, it will no longer be atomic.

IMO, threading problems are too complex to take risks.

0
Sep 12 '08 at 1:03
source share

Let's look at this example.

int x; x++; x=x+5; 

The first statement is considered atomic because it is converted to a single INC assembly directive, which takes one CPU cycle. However, the second assignment requires several operations, so this is clearly not an atomic operation.

Another for example

 x=5; 

Again, you need to parse the code to see what exactly is happening here.

0
Jul 31 '10 at 16:39
source share

T, I think that at that moment when you use a constant (for example, 6), the instruction will not be completed within one machine cycle. Try to see the x + = 6 instruction set compared to x ++

0
Aug 19 '10 at 9:22
source share

Some people think ++ c is atomic, but watch out for the assembly you created. For example, using "gcc -S":

 movl cpt.1586(%rip), %eax addl $1, %eax movl %eax, cpt.1586(%rip) 

To increment an int, the compiler first loads it into a register and saves it back to memory. It is not atomic.

0
Mar 28 2018-12-12T00:
source share

Finally, NO! This answer is from our top authority C ++, M. Boost:
Operations with "ordinary" variables are not guaranteed to be atomic.

0
Oct 22 '13 at 9:13
source share

The only portable way is to use the sig_atomic_t type defined in the signal.h header for your compiler. In most C and C ++ implementations, this is int. Then declare the variable as "volatile sig_atomic_t."

-one
May 09 '10 at 1:47 a.m.
source share



All Articles