In C# setting a value to a variable is atomic as long as its size is at most native int (i.e. 4 bytes in a 32-bit runtime environment and 8 bytes on a 64-bit one).
In a 64-bit environment that includes all references types and most built-in value types (byte, short, int, long, etc.).
Setting a bigger value isn't atomic and can cause tearing where only part of the memory is updated.
DateTime is a struct that includes only a single ulong field containing all its data (Ticks and the DateTimeKind) and ulong by itself is atomic in a 64-bit environment.
Does that mean that DateTime is atomic as well? Or Can the following code lead to tearing at some point?
static DateTime _value;
static void Main()
{
for (int i = 0; i < 10; i++)
{
new Thread(_ =>
{
var random = new Random();
while (true)
{
_value = new DateTime((long)random.Next() << 30 | (long)random.Next());
}
}).Start();
}
Console.ReadLine();
}
From the ECMA specification section "I.12.6.6 Atomic reads and writes"
A
native intis aIntPtrin C#.So long as
sizeof(IntPtr) >= sizeof(DateTime)is true for the runtime environment (aka: running as 64 bit), and they don't alter the internal structure to be explicit layout with misaligned bytes instead of the[StructLayout(LayoutKind.Auto)]it currently has, then reads and writes of aDateTimestruct (or any other struct that follows those rules) are guaranteed to be atomic by the ECMA specification.You can verify that by running the following code in a 64-bit environment: