Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Volatile Violates its main job?

According to MSDN:

The volatile keyword indicates that a field might be modified by multiple threads that are executing at the same time. Fields that are declared volatile are not subject to compiler optimizations that assume access by a single thread. This ensures that the most up-to-date value is present in the field at all times.

Please notice the last sentence:

This ensures that the most up-to-date value is present in the field at all times.

However, there's a problem with this keyword.

I've read that it can change order of instructions:

First instruction       Second instruction         Can they be swapped?
Read                         Read                         No
Read                         Write                        No
Write                       Write                         No 
Write                       Read                          Yes! <----

This means John sets a value to a volatile field, and later Paul wants to read the field, Paul is getting the old value!

What is going here ? Isn't that it's main job ?

I know there are other solutions, but my question is about the volatile keyword.

Should I (as a programmer) need to prevent using this keyword - because of such weird behavior ?

like image 301
Royi Namir Avatar asked May 17 '12 07:05

Royi Namir


People also ask

What does volatile do in c#?

The volatile keyword in C# is used to inform the JIT compiler that the value of the variable should never be cached because it might be changed by the operating system, the hardware, or a concurrently executing thread.

What is volatile bool?

That is, as far as I understand, when you use the Visual C++ compiler, a volatile bool is for most practical purposes an atomic<bool> . It should be noted that newer VS versions add a /volatile switch that controls this behavior, so this only holds if /volatile:ms is active.


3 Answers

Well you are right. It is more elaborated in Joseph Albahari threading book/article.

The MSDN documentation states that use of the volatile keyword ensures that the most up-to-date value is present in the field at all times. This is incorrect, since as we’ve seen, a write followed by a read can be reordered.

http://www.albahari.com/threading/part4.aspx#_The_volatile_keyword

Should I ( as a programmer ) need to prevent using this keyword-because of such weird behavior?

It should be used only after knowing this weired behavior. It should not be used as a Magic keyword to retrieve latest values all the time in multithreaded environment.

IMO, usage of volatile keyword should be avoided as probable bugs are hard to find out.

like image 140
Tilak Avatar answered Sep 20 '22 16:09

Tilak


The MSDN documentation is wrong. That is most certainly not what volatile does. The C# specification tells you exactly what volatile does and getting a "fresh read" or a "committed write" is not one of them. The specification is correct. volatile only guarantees acquire-fences on reads and release-fences on writes. These are defined as below.

  • acquire-fence: A memory barrier in which other reads and writes are not allowed to move before the fence.
  • release-fence: A memory barrier in which other reads and writes are not allowed to move after the fence.

I will try to explain the table using my arrow notation. A ↓ arrow will mark a volatile read and a ↑ arrow will mark a volatile write. No instruction can move through the arrowhead. Think of the arrowhead as pushing everything away.

In the following analysis I will use to variables; x and y. I will also assume that they are marked as volatile.

Case #1

Notice how the placement of the arrow after the read of x prevents the read of y from moving up. Also notice that the volatility of y is irrelevant in this case.

var localx = x; ↓ var localy = y; ↓ 

Case #2

Notice how the placement of the arrow after the read of x prevents the write to y from moving up. Also notice that the volatility of either of x or y, but not both, could have been omitted in this case.

var localx = x; ↓ ↑ y = 1; 

Case #3

Notice how the placement of the arrow before the write to y prevents the write to x from moving down. Notice that the volatility of x is irrelevant in this case.

↑ x = 1; ↑ y = 2; 

Case #4

Notice that there is no barrier between the write to x and the read of y. Because of this the either the write to x can float down or the read of y can float up. Either movement is valid. This is why the instructions in the write-read case can be swapped.

↑ x = 1; var localy = y; ↓ 

Notable Mentions

It is also important to note that:

  • x86 hardware has volatile semantics on writes.
  • Microsoft's implementation of the CLI (and suspect Mono's as well) has volatile semantics on writes.
  • The ECMA specification does not have volatile semantics on writes.
like image 24
Brian Gideon Avatar answered Sep 17 '22 16:09

Brian Gideon


Another point raised by Joseph Albahari is that process architecture can adversely impact volatile, i.e. AMD in particular can cause values to be swapped.

Since you will probably have no idea what system type your application will run on in production its best to always avoid the volatile keyword.

Also slightly off topic you should always avoid the ReaderWriterLock class as under heavy load on multiprocessor systems this can allow multiple write locks please see here to be taken simultaneously which will cause application hangs which will be extremely difficult to root cause

like image 34
Johnv2020 Avatar answered Sep 19 '22 16:09

Johnv2020