24

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 ?

Royi Namir
  • 144,742
  • 138
  • 468
  • 792
  • @Corbin press on the `ive read` link . – Royi Namir May 17 '12 at 07:39
  • Ah ok. That makes sense then. One second and I'll elaborate. Edit: Ok I take that back. It makes sense in my head, but I can't explain it >.<. – Corbin May 17 '12 at 07:41
  • 1
    I've been staring at the standard for the past 10 minutes trying to decide if this is aligned with the standard or not. As MS was implementing a standard they wrote, I suppose it is, however, the language is vague at best. For anyone intersted, it's section 10.5.3 of http://go.microsoft.com/fwlink/?LinkId=199552 Edit: section 3.10 is also of interest. – Corbin May 17 '12 at 07:58
  • 6
    [Eric Lippert](http://blogs.msdn.com/b/ericlippert/archive/2011/06/16/atomicity-volatility-and-immutability-are-different-part-three.aspx) has a nice article on the subject (as usual), as does [Joe Duffy](http://www.bluebytesoftware.com/blog/2010/12/04/SayonaraVolatile.aspx). – Joey May 17 '12 at 08:10
  • @Joey it doesnt talk about that particular case of ordering in statements. – Royi Namir May 17 '12 at 08:14
  • 1
    Another Joe Duffy post that discusses this is here http://www.bluebytesoftware.com/blog/PermaLink,guid,dd3aff8a-7f8d-4de6-a2e7-d199662b68f4.aspx In particular, he outlines what can and cannot be rearranged. Basically a text form of the table posted, but I like his explanation of "Note that RELEASe is the opposite of ACQUIRE: you can think of an acquire as a one-way fence that prohibits passes downward, and a release as a one-way fence that prohibits passes upward." – Corbin May 17 '12 at 08:29
  • @Corbin I think he has a mistake. it should be _acquire as a one-way fence that prohibits passes **upward**, and a release as a one-way fence that prohibits passes **downward**._ – Royi Namir Mar 01 '13 at 20:21

3 Answers3

18

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.

Tilak
  • 30,108
  • 19
  • 83
  • 131
  • 3
    why doesnt msn write this weird behaviour ? why do i need to hear it from joseph ? – Royi Namir May 17 '12 at 07:43
  • 4
    I dont know. MSDN is factually incorrect at various places. I can see the user comments pointing out that. In the Joseph's article, the conclusion is backed by suitable example which you can try out yourself. – Tilak May 17 '12 at 07:45
7

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.
Brian Gideon
  • 47,849
  • 13
  • 107
  • 150
  • i know, see my question about this topic http://stackoverflow.com/questions/10589654/half-fences-and-full-fences – Royi Namir May 17 '12 at 14:08
  • hhh you answered it already there.....lol. i still need to check some more knowledge before i check an answer ....( for the link question) – Royi Namir May 17 '12 at 14:08
  • @RoyiNamir: Take a look at [this](http://stackoverflow.com/q/10281044/158779) question where I analyze the double-checked locking pattern using the arrow notation I came up with. The arrow notation really helps when trying to visualize what can and cannot happen. – Brian Gideon May 17 '12 at 14:22
  • Listen man , you've helped me a lot. great detailed answer. you are trully a Thread Expert. – Royi Namir May 18 '12 at 07:58
  • after reading some articles and seeing images about this topic - i think the read should have its arrow up ( the head tells that instructions from down cant go up - so the head is blocking.)....the write should have its arrow down - so it shows that prev instructions cant go down.... http://techpubs.sgi.com/library/tpl/cgi-bin/getdoc.cgi?coll=linux&db=bks&fname=/SGI_Developer/LX_DevDriver_PG/apa.html – Royi Namir May 18 '12 at 14:16
  • 1
    No, that would not be right. I use the arrows to show what *cannot* happen. The link you provided uses them to show what *can* happen. We both agree on principals though...which is good :) – Brian Gideon May 18 '12 at 19:25
  • Are those reads/writes regarding to read/writes from the same thread or from other threads too ...? – Royi Namir Mar 01 '13 at 15:46
  • @RoyiNamir: It is from the perspective of *other* threads. The same thread will always perceive reads/writes in the order they were entered in the program code...otherwise no program would work correctly. Good question. – Brian Gideon Mar 01 '13 at 21:45
4

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

Community
  • 1
  • 1
Johnv2020
  • 2,088
  • 3
  • 20
  • 36