2

I know that there is a lot of questions about volatile but I just got confused from this discussion: Java: how volatile guarantee visibility of "data" in this piece of code?

Every web site that I read says that a variable could be stored in cached ( making this value invisible for another threads ) I even found this example https://dzone.com/articles/java-volatile-keyword-0

So my first question would be: Does Java stores variable values in cache memory ( in which one ? l1 l2 or l3 )

My other question is the visibility part. For example:

public int num1 = 1;
public int num2 = 2;
public int num3 = 3;
public int num4 = 4;
public int num5 = 5;
...
num1 = 10;
num2 = 20;
num3 = 30;
num4 = 40;
num5 = 50;

In this example the execution order of variables is not guaranteed. If I make num2 volatile it assures me that the order execution of num1, num2 and num3 will be exactly like its defined, but its not assuring me for num4 and num5 ?

EDIT I just finished reading the article of Peter Lawrey http://vanillajava.blogspot.com.es/2012/01/demonstrating-when-volatile-is-required.html and he wrote "Without volatile, this breaks down in a number of possible ways. One way is that the two threads each think they have changed the value and are waiting for the other i.e. each has its own cached copy of the value. "

Sooo I'm even more confused .. about that

Sorry for the probably dumb question but I really confused about that.

Community
  • 1
  • 1
JDoe
  • 66
  • 7

3 Answers3

3

Most programs, including the JVM do not explicitly place variables in any particular cache. The only decision the JIT makes is

  • does it eliminate the variable entirely?
  • does it place it in a register and which one?
  • does it place it on the stack in memory? (And where relative to the top of the stack)
  • does it place it in an object on the heap? (And where in the object)

The only choice you have is whether the variable is in an object or on the stack. (You also have the choice to avoid using a variable at all) note, if you place the field in an object the jit can still put it only the stack if it can avoid creating the object.

The only visibility guarantee that making num2 volatile provides is that if you see num2 == 20 you must see num1 == 10. You are also guaranteed you will see num2 == 20 at some point in other threads. You may see num3 == 3 or num3 == 30. It's possible you might never see num3 in another thread as it's not volatile or final. You might see num3 == 0 which is the uninitialised value if you read that field in another thread before num2 is written a second time.

each has its own cached copy of the value.

This is not determined by Java but is an implementation detail of CPUs. Each core has it's own L1 and L2 caches in x64, Sparc and ARM. These caches are local to each core for speed which means they might not be in sync with each other. Ensuring they are always in sync would slow them down dramatically.

Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130
  • 10x for answering Peter. So when a variable is volatile guarantees that all the above variables will be in the exact same order as there were defined, but no guarantees for the variables below. For example if i define num4 as volatile 1,2,3 and 4 will be executed in order but from 5 will be no guarantee ? In this question [Link](http://stackoverflow.com/questions/33641966/java-how-volatile-guarantee-visibility-of-data-in-this-piece-of-code) David said that volatile has nothing to do with caches. Im still a bit confused. I think I understand that java has nothing to do with where and how .... – JDoe Nov 11 '15 at 15:36
  • a variable will be stored. But why is it said in this question that volatile has nothing to do with cache ? – JDoe Nov 11 '15 at 15:39
  • @JDoe They will be in order if they are all volatile. However if just one is volatile, you when you see a new value for it, you bust see the previous values for others. – Peter Lawrey Nov 11 '15 at 15:50
  • @JDoe He is right that volatile is about visibility between threads, the spec doesn't say anything about caches and if you had a CPU which didn't have any caches it would still work. However in most CPUs like x64 and ARM, the cache will be involved in making this visibility happen as described. – Peter Lawrey Nov 11 '15 at 15:52
  • (About the order) What I meant is that if variable 4 is volatile it will be executed after 1,2,3 and before 5 ?! ( is that so right ? ). (About cache) So a volatile variable has nothing to do with the cache ( the cache is CPU problem ) what volatile will "require" is to get the most recent value of that variable ( no matter from where ) ??? – JDoe Nov 11 '15 at 16:17
  • Volatile is not directly related to the cache however all memory access go through the cache and if a CPU has a cache it must be involved. if you read volatile 4 you must see an up to date 1,2,3 but you are likely see an up to date 5. – Peter Lawrey Nov 11 '15 at 17:26
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/94858/discussion-between-jdoe-and-peter-lawrey). – JDoe Nov 11 '15 at 21:28
  • ( I have the order part clear ). When a variable is not volatile some time when I read it has a steal value. Why is that happening ? Because it get the value from cache/registry that is "dirty" or changed it main memory ? – JDoe Nov 11 '15 at 22:44
  • @JDoe you see a stale value because the copy of the variable in your cpus cache us out of date. In fact it is possible the variable has been written in two other threads and yet you could see a new value or a random choice of the ones written. – Peter Lawrey Nov 12 '15 at 22:59
  • its basically what I said right ? Volatile variables require the most recent value. I was reading about MESI Protocol. A value in cache can be modified , invalid, exclusive, shared. In technical level when Java cant know where and how is stored the value of a variable ( I suppose ) so when a variable is volatile it just requires the most recent value ... Its what I basically understand. And if its not a volatile it could get a modified or invalid variable ( if it is from cache ). – JDoe Nov 13 '15 at 01:07
  • @JDoe without volatile or synchronized or a thread safe construct, it could get an old value it loaded previously. Even more importantly, it might never see the new value. If a thread never modify a variable it can inline it in code like `final` – Peter Lawrey Nov 16 '15 at 23:14
0

When you look for an exact description of such behaviour, it's always good to have a look into the Java Language Specification. In the linked chapter, you'll find information about threading behaviour and compiler reordering and how volatile comes into play here.

Alexander Rühl
  • 6,769
  • 9
  • 53
  • 96
0

The order of the assignments is not affected by volatile. The keyword volatile guarantees that multiple threads accessing e.g an int-value 'see' the same value. The value of this variable will never be cached thread-locally: all reads and writes will go straight to "main memory". Access to the variable acts as though it is enclosed in a synchronized block, synchronized on itself.

Chriss
  • 5,157
  • 7
  • 41
  • 75
  • A cacheline doesn't need to be written to main memory; it is fine to live within the caches indefinitely. The MESI protocol will make sure the value is coherent over the caches of all CPU's. But volatile will not flush something from cache to main memory. What volatile write does is make sure that the store buffer is drained to the L1D cache before a next load is executed. – pveentjer May 19 '20 at 12:14