3

Quick question. Is below assignment atomic:

object [] table = new object[10]
...
table[3] = 10; //is it atomic ?
...
Henrik
  • 23,186
  • 6
  • 42
  • 92

3 Answers3

5

Yes, the assignment is atomic because object is a reference type.

As mentioned in the below quote from MSDN writes are atomic for most (not all) of buil-in value types (mentioned below) and reference types. The CLI guarantees that reads and writes of variables of value types that are the size (or smaller) of the processor's natural pointer size are atomic; if you are running C# code on a 64 bit operating system in a 64 bit version of the CLR then reads and writes of 64 bit doubles and long integers are also guaranteed to be atomic. The C# language does not guarantee that, but the runtime spec does.

what MSDN says

Reads and writes of the following data types are atomic: bool, char, byte, sbyte, short, ushort, uint, int, float, and reference types. In addition, reads and writes of enum types with an underlying type in the previous list are also atomic. Reads and writes of other types, including long, ulong, double, and decimal, as well as user-defined types, are not guaranteed to be atomic. Aside from the library functions designed for that purpose, there is no guarantee of atomic read-modify-write, such as in the case of increment or decrement.

A very detailed answer by none other than Eric himself can be seen here

Community
  • 1
  • 1
Ehsan
  • 31,833
  • 6
  • 56
  • 65
  • 1
    But what about the array access? – Dirk Aug 23 '13 at 06:36
  • 3
    What about the boxing? It's an `object` array, not `int` array. – Alex Aug 23 '13 at 06:37
  • I don't see any boxing in the question you link to. – Alex Aug 23 '13 at 06:42
  • @Alex it will still be atomic, otherwise MSDN must had stated explicitly somewhere. i didn't find it anywhere (if you do, let me know as well, i will really appreciate that). – Ehsan Aug 23 '13 at 06:48
  • The way I see it there are two atomic operations during the assignment - assigning an int to a boxing object, and assigning the boxing object reference to the reference in the array. So I agree it can be though of as atomic (in the sense that it's going to yield a well-defined result), even though it's actually two atomic operations and the value of the `int` can change between them. It would have been nice to note this in the answer, though. – Alex Aug 23 '13 at 06:54
  • @Alex from whatever i have read, assignment is said to be an atomic operation. And though in this case it involves 2 steps but even then, it will either be written or not and therefore no intermediate state. So it is atomic – Ehsan Aug 23 '13 at 07:08
3

I am assuming OP means 'thread safe' when talking about atomicity.

A write operation is not atomic only if it is possible that another thread can read partially written value.

If object [] table is local to a method, each thread will get their own table and hence any operation on the table will be atomic.

Going forward I am assuming that table is shared across threads.

OP has defined table as an array of object. Hence table[3] = 10 involves boxing.

Even though table[3] = 10 represents a chain of instructions, this operation is atomic because this will eventually be writing the 'address' of the boxed instance (Current CLR implementation do represent object reference using memory address) and addresses are of the natural word size of the machine (i.e. 32 bit on 32 bit machines and 64 bit on 64 bit machines). Please note that even though above explanation is based on current CLR implementation, atomicity of reference writing is guaranteed by specs. The operation of boxing and the boxed instance itself are local to the thread and hence there is no way that another thread can interfere in that. Going by same reasoning even if a value exceeding the word size (for e.g. Decimal) was being written, the operation would have been atomic (due to boxing). It must be noted here that the above argument holds only if the value being written has already been obtained in a thread safe manner.

Had no boxing been involved, then the usual rules of word size writes (or sizes lesser than the word size, owing to memory alignment) being atomic holds.

Amit Mittal
  • 2,646
  • 16
  • 24
2

I seriously doubt that the entire term table[3] = 10; is atomic. While a single read or write to some data types are atomic array acces is most likely not.

The IL code for your example is

IL_0001:  ldc.i4.s    0A 
IL_0003:  newarr      System.Object
IL_0008:  stloc.0     // table
IL_0009:  ldloc.0     // table
IL_000A:  ldc.i4.3    
IL_000B:  ldc.i4.s    0A 
IL_000D:  box         System.Int32
IL_0012:  stelem.ref

You can see that the index is loaded at IL_000A, then a boxing of the int occurs at IL_000D and finally the boxed value is stored at IL_0012.

Each indidivual of these instructions might be atomic, but that doesn't mean that the chain of instructions that make table[3] = 10; is.

Dirk
  • 10,668
  • 2
  • 35
  • 49