I have found several questions about this same topic but related to general variables (value and reference types)
The accepted answer from this question says:
Partition I, Section 12.6.6 of the CLI spec states: “A conforming CLI shall guarantee that read and write access to properly aligned memory locations no larger than the native word size is atomic when all the write accesses to a location are the same size.”
Reference variables (i.e. classes) are pointers, equal to the native word size, but I have a couple doubts:
Are references guaranteed to be in properly aligned memory locations?
I don’t understand the last part. What does this mean? “…when all the write accesses to a location are the same size.”
In short, is obj2 guaranteed to be valid in every iteration of the loop in the following code?
class MyClass
{
private OtherClass m_Object;
void Thread1()
{
while(true)
{
OtherClass obj1 = new OtherClass();
m_Object = obj1;
}
}
void Thread2()
{
while (true)
{
OtherClass obj2 = m_Object;
// Is obj2 guaranteed to be valid?
obj2.Check();
}
}
}
Yes, everything is guaranteed to be properly aligned unless you deliberately go out of your way to misalign stuff, meaning that reference assignment/reading is guaranteed to be atomic.
Section 12.6.6 of the CLI spec goes on to say this:
There are also further details about alignment etc in section 12.6.2 of the spec.
Note that in your example code, the read in thread 2 is guaranteed to be atomic, but it’s not guaranteed to actually see any changes made by thread 1: without enforcing memory barriers or volatility each thread can use its own “view” of the
m_Objectfield without ever seeing changes made by other threads.So, for example, thread 1 could be making (atomic) writes into its own view of
m_Object, but the data is only ever actually held in a register or CPU cache and never comitted to main memory. Similarly, thread 2 could also be making (atomic) reads ofm_Object, but actually reading from a register or CPU cache rather than main memory.