8

I read this in the book C# 6.0 and the .NET 4.6 framework:

“assignments and simple arithmetic operations are not atomic”.

So, what does it exactly mean?

mshwf
  • 7,009
  • 12
  • 59
  • 133
  • Have a look [here](http://programmers.stackexchange.com/questions/241017/what-is-atomicity) – Blue Aug 02 '16 at 13:58
  • 1
    Possible duplicate of [What operations are atomic in C#?](http://stackoverflow.com/questions/11745440/what-operations-are-atomic-in-c) – Gilad Green Aug 02 '16 at 13:58
  • https://en.wikipedia.org/wiki/Linearizability#Primitive_atomic_instructions – Remus Rusanu Aug 02 '16 at 14:01
  • This article may help you http://wayneye.com/ViewBlog.aspx?Permalink=Atomic-Operation-In-Csharp – gofr1 Aug 02 '16 at 14:01
  • Go to http://stackoverflow.com/questions/11745440/what-operations-are-atomic-in-c here are complete definition of your question. – akber Aug 02 '16 at 14:03
  • I don't know what does atomic mean, so knowing what operations are atomic doesn't help me, if one of you write a book, there is a chance to have two titles in the chapter explaining this topic: 1: what is atomic? 2: what operation are atomic? You can't start with the second title. Condemning my question as a duplicate version increase the possibilities to be blocked from the site, so please understand my question. – mshwf Aug 02 '16 at 14:21
  • If you didn't understand my explanation, then tell my why and where, please. Giving examples for atomic operations and telling why they are atomic seems to be the most understandable approach. Furthermore, there are already many resources on the Internet about atomicity. Search them and you'll surely learn more. – cadaniluk Aug 02 '16 at 14:32

2 Answers2

36

Atomic operations are ones that cannot be interrupted partway through, such as by threading. Take for instance the statement

_value++;

If you have two threads executing this code at once with a starting value of 0, you may have the following

  • Thread A reads _value, 0
  • Thread A adds 1, 1
  • Thread B reads _value, 0
  • Thread B adds 1, 1
  • Thread A assigns to _value, 1
  • Thread B assigns to _value, 1

so now, even though we've called an increment twice, the final value in _value is 1, not the expected 2. This is because increment operators are not atomic.

The function Interlocked.Increment, however, is atomic, so replacing the above code with

Interlocked.Increment(ref _value);

Would solve the given race condition.

EDIT: As a point of etymology, "atomic" originally meant "indivisible" - the chemistry term we're familiar with is a misnomer held over from the belief that atoms were indivisible, only for later discoveries to break them down further into subatomic, quark, and quanta levels.

David
  • 10,458
  • 1
  • 28
  • 40
11

An atom is indivisible. Atomic operations are "indivisible" operations, which cannot be divided, e.g., interrupted.

Microprocessors do not execute sequentially, that is, instruction after instruction, just like written in a program. There are external objects, which can change execution flow. A good example are interrupts.

So, you may know the MOV instruction, which is available on pretty much all processors.
Imagine that it is executed by the CPU. a 32-bit value is moved into a 32-bit register.
Now, after 16 bits have been moved, an interrupt request occurs.

  • An atomic MOV instruction will not stop but will execute to the end and then the CPU will handle the interrupt
  • A MOV instruction that is not atomic will immediately be stopped and the interrupt is executed. The problem is, if the interrupt accessed the register, which was written to by the MOV, the content is unclear because the MOV operation is only half-finished!

Now, on usual processors, MOVs operating on the processor's word size are atomic. If a processor word is 16 bits wide, a 16-bit MOV instruction will be atomic.
However, a 32-bit MOV operation would not be atomic. Such a non-atomic MOV instruction is normally not provided by the instruction set but by some higher-level language as with C's long long or C#'s long. Operations on these data types are not guaranteed to be atomic!

cadaniluk
  • 15,027
  • 2
  • 39
  • 67
  • Is there an example on this? – mshwf Aug 02 '16 at 14:00
  • 1
    @MohamedAhmed Example added. – cadaniluk Aug 02 '16 at 14:05
  • @cadaniluk: Many processors specify circumstances in which interrupts will not occur. On an 80386sx processor (like an 80386, but with a 16-bit data bus), a 32-bit read or write will be performed as two 16-bit operations, but most kinds of interrupts cannot be serviced between them. I think it might be possible for a bus fault to occur when the instruction is half-processed, but if such an interrupt occurs on a read, the value that was read in the first half of the operation will be discarded, and the entire read re-executed from scratch. If a bus fault occurs mid-write, ... – supercat Dec 13 '20 at 17:22
  • ...the entire write would be re-executed from scratch, so that any write which completes will have done so atomically, *but* the write operation would end up writing the first half of the destination both before and after the page fault handler. Most systems are designed, however, so that such a sequence of events could not occur if the access is performed at a multiple-of-four address. – supercat Dec 13 '20 at 17:29