I can think of a number of use cases where it would be very useful to have DateTime objects be atomic. What are the advantages from a language design standpoint to not make DateTime volatile?
-
Using lock is only reliable way longterm. Volatile only turns off compiler optimisations that might cause **additional** Issue. Issues on top of those you get in Multitasking or even Multithreading scenarios. DateTime might not **have** those Compiler Optimisations to begin with. So turning them off would make no sense. – Christopher May 19 '18 at 00:41
3 Answers
The volatile
keyword does not guarantee atomicity. Atomicity is guaranteed for all data types of 32-bits or fewer, with or without the keyword.
The purpose of the volatile
keyword is to ensure that all threads are looking at the same copy of the variable. You may be surprised to learn there could be more than one copy: they could be held in main memory, as you'd expect, but also in one or more levels of CPU cache or in a CPU register.
When you use the volatile
keyword, the compiler will emit a couple extra instructions ("memory barriers") and skip certain optimizations to ensure that all threads will see the same copy of the variable. That's all it does.
For types that are bigger than 32 bits, you need a lock
anyway, and a lock will automatically put those memory barriers in place. So volatile isn't needed for those variables; surround the code that accesses the variable with a lock
instead.

- 50,556
- 8
- 44
- 80
-
1
-
One piece might be missing: that DateTime is a 64-bit type to begin with. Internally it stores the Number of Ticks since "moment X" as a unsigned Int64. All other properties (days, month, week) - even the ToString() representation - are just an interpretation of that Internal value. With moment X being usually "the start of the Unix Time", wich is 1st January 1970. Of course if that option is not supported for Int64, it is not supported for a type that contains an Int64. – Christopher May 19 '18 at 12:44
-
3@Christopher: No, for .NET `DateTime` the epoch (which you call "moment X") is not the Unix epoch. [The documentation](https://msdn.microsoft.com/en-us/library/system.datetime.ticks.aspx) is quite clear that it measures from 1st January 0001. – Ben Voigt May 19 '18 at 15:52
The volatile
keyword may only be applyed to fields which are atomically updatable, such as int,long reference types etc. (see docs for more).
One way to get the desired behaviour are lock statements. Which will ensure only one thread at a time can enter a "locked" section of the code (also known as a crititcal section).

- 352
- 4
- 11
-
1`System.Int64` (long) is one of the types it cannot be used on. – Jonathon Chase May 19 '18 at 00:37
-
@JonathonChase: volatile turns off certain Compiler Optimisations. The types you can not apply it too might not have those optimisations applied to them to begin with. And you can hardly turn off, wich is not even avalible as a option to being with? – Christopher May 19 '18 at 00:44
-
@Christopher Are you sure? Which optimizations does volatile deactivate? My understanding is that it marks the field `IsVolatile` and lets the runtime take it from there. – Jonathon Chase May 19 '18 at 00:55
There is a number of Compiler and JiT Compiler optimisations in place. For example if you write:
{
int temp = Int32.Parse(input);
Console.WriteLine(temp);
}
The JiT might think outside of debug builds: "Hey, that int variables is not actually used anywhere else. I can propably compile it like this":
Console.WriteLine(Int32.Parse(input));
And it will have the exact same result."
When people have such nested calls I often adivse to split them up using temporary variables, knowing full well that the JiT can (and propably will) take care of them. There will be no relevant performance impact from this change, but a relevant improovement of readabiltiy and debugability.
The compiler can also go the opposite way. For example if you call the same Index twice, it will actually try to save a Index Bound check by adding a temproary variable. When you expected a fresh value, you might be actually working with a local copy.
But with Multitasking and Multithreading any such Optimsiation might give you a ton of extra headaches. volatile turns off those kinds of optimisations. But it can only do so, if the type has that optimisation to begin with.

- 9,634
- 2
- 17
- 31