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();
}
ConcurrentDictionary
's implementation doesn't treatDateTime
as atomic, which makes me wonder: ConcurrentDictionary.IsValueWriteAtomic – PasternDateTime
is atomic. – FabriceDateTime
fits this category on a 64-bit system. However,ConcurrentDictionary
appears to be much more conservative than the standard: it will not consider no-larger-than-native-intstruct
s as atomic, it will only consider built-in primitive data types as atomic. Conventional wisdom says it is probably a flaw inConcurrentDictionary
, but note how I am writing a comment and not an answer! C-:= – KyteDateTime
et al. and the shape of the API (which unfortunately works just well enough for the simple cases). There's some random gotchas which make certain use cases impossible to solve natively. – Dregs