• Post Reply Bookmark Topic Watch Topic
  • New Topic

Understanding volatile keyword

 
Suhaas Mohandos
Greenhorn
Posts: 21
1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
By definition of volatile:

By making a variable volatile using the volatile keyword in Java, application programmer ensures that its value should always be read from main memory and thread should not use cached value of that variable from their own stack.

I want to understand if I don't use volatile keyword why the main memory value of a variable say x is different from it's cached value. In multithreading when exactly the local cache is updated and when main memory will be updated if not using volatile.

Appreciate an example
 
M Khalid
Ranch Hand
Posts: 50
2
Java
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Volatile keyword in Java is used as an indicator(tag) to Java compiler and Thread,  that do not cache value of this variable and always read it from main memory.
If you want to share a variable in which read and write operation is performed and is atomic then you can declare it as volatile.
The Java volatile keyword cannot be used with method or class and it can only be used with a variable.
Use of volatile keyword also prevents compiler or JVM from the reordering of code or moving away from synchronization

for Example we use Singleton class instance:

If we do not make the instance variable volatile than the Thread which is creating instance of SingletonDemo is not able to communicate other thread, that instance has been created until it comes out of the SingletonDemo block.

So for example if Thread A is creating SingletonDemo instance and just after creation lost the CPU, all the other thread will not be able to see value of instance (sInstance in example) as not null and they will believe it is still null.
The reason is because reader threads (suppose Thread B) are not doing any locking and until writer thread (suppose Thread A) comes out of synchronized block, memory will not be synchronized and value of instance(sInstacne) will not be updated in main memory.




 
Tapas Chand
Ranch Hand
Posts: 602
9
BSD Java
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Suhaas Mohandos wrote:In multithreading when exactly the local cache is updated and when main memory will be updated if not using volatile.

Write policy varies from system to system, from single processor to multi processor units. I think you should not care about the write policy much, Java keeps us away from hardware specific things and it does well in that.
Still if you are interested, I was going through below link few months back, a starting point.
Link
 
Suhaas Mohandos
Greenhorn
Posts: 21
1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Ok thanks. So can I conclude that if a variable is declared as volatile then both read and write of that variable happens from main memory and the cache is not updated?
 
Tapas Chand
Ranch Hand
Posts: 602
9
BSD Java
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Suhaas Mohandos wrote:...if a variable is declared as volatile then both read and write of that variable happens from main memory
You are right.

Suhaas Mohandos wrote:and the cache is not updated?
I am not sure about this.
 
Stephan van Hulst
Bartender
Posts: 6583
84
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Suhaas Mohandos wrote:By definition of volatile:

By making a variable volatile using the volatile keyword in Java, application programmer ensures that its value should always be read from main memory and thread should not use cached value of that variable from their own stack.

Where did you get that definition? I don't think that's the definition of volatile.

When you write to a volatile variable, it is guaranteed this action happens-before any subsequent reads. Happens-before is a strongly defined term in the JLS. There is no mention of caches however.
 
Tapas Chand
Ranch Hand
Posts: 602
9
BSD Java
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Stephan van Hulst wrote:There is no mention of caches however.

O wow...I never looked at JLS for volatile. It indeed does not mention about cache.

But I have been linking volatile with cache may be because it was taught like that.
Or may be because a lot of sites explain volatile that way.
e.g. 1st result on google -> Link

Thank you Stephan for mentioning happens-before
 
Daniel Cox
Ranch Hand
Posts: 147
7
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
The JLS does say that all threads see a consistent value for a volatile field. The only way this can happen is if the value is never cached.
 
Henry Wong
author
Sheriff
Posts: 22532
109
C++ Chrome Eclipse IDE Firefox Browser Java jQuery Linux VI Editor Windows
  • Likes 2
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
The main reason the JLS doesn't mention "cache", IMHO, is caching is an implementation detail. Also, it leads to the next question ... which cache?

In terms of caching (making a copy of the variable not in memory), I believe that the two main ones that affects volatile are the Processor Cache and one of the compiler optimizations..

Unfortunately, the first is a cache that is an implementation detail of the JVM (and its something that the JVM uses, and not implements), and the second, is technically, not a cache (although, it is a copy of the variable).

Henry
 
Suhaas Mohandos
Greenhorn
Posts: 21
1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Ok, so if I am not using volatile does cache come in picture?
 
Campbell Ritchie
Marshal
Posts: 52580
119
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
It might; the JVM might use the value in the cache, or the value in the register, or the value in RAM. You do not know which.
 
Suhaas Mohandos
Greenhorn
Posts: 21
1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Ok. Can I assume that since the JLS does not mention anything regarding cache in the definition of volatile, cache is not used for a volatile variable?
 
Campbell Ritchie
Marshal
Posts: 52580
119
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
What does the JLS say? Is it in this section? That section refers to another section; go through that with ctrl‑F‑“volatile” You will see that reads and writes of volatile variables are done as if synchronised, and as if atomic, and they have a happens‑before relationship with one another. It does not actually say that it reads from RAM. Let's try the JVM Specification. That doesn't seem to say anything about volatile at all.
 
Stephan van Hulst
Bartender
Posts: 6583
84
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
No you can't assume that, because it's an implementation detail. Besides, 'cache' is very vague. What cache?

If at some stage they manage to run Java on crystal balls, there won't be any memory or registers to speak of in the first place. The sections in the JLS about volatile variables are perfectly compatible with this state of affairs.
 
Daniel Cox
Ranch Hand
Posts: 147
7
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Suhaas Mohandos wrote:Ok. Can I assume that since the JLS does not mention anything regarding cache in the definition of volatile, cache is not used for a volatile variable?

Without the volatile keyword, a thread assumes that a field is final (or if it is not final, it is not modified by multiple threads) and so it is free to use a performance improvement optimization (maybe cache, maybe something else) which may result in threads not seeing a consistent value for a field (if the field is not final and is modified by multiple threads).

Use the volatile keyword to explicitly make threads aware that a field is not final and it is may be modified by multiple threads and so they cannot use this optimization.

The volatile field will then be used in manner that results in the following:
  • all threads will see any change made to the field i.e. all threads will see a consistent value for the field
  • all threads will see the side effects that happen before a change is made to the field
  • all reads from and writes to the field will be atomic

  •  
    Ganesh Patekar
    Bartender
    Posts: 696
    23
    Eclipse IDE Hibernate Java jQuery MySQL Database Netbeans IDE Oracle Spring Tomcat Server
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Here are few resources who do mention about volatile fields are not catched
    JVMS Java SE 8 4.5. Fields wrote:
    Each field is described by a field_info structure.
    The structure has the following format:
    field_info {
        u2             access_flags;
    u2             name_index;
        u2             descriptor_index;
        u2             attributes_count;
        attribute_info attributes[attributes_count];
    }
    In access_flags:
    Flag NameValueInterpretation
    ACC_VOLATILE0x0040Declared volatile; cannot be cached.

    Source

    JavaTM Performance by Charlie Hunt and Binu John Page Ch 6 No 234 wrote: a volatile field’s value must be kept in sync across all application threads and CPU caches. For instance, when a volatile field’s value is changed by one thread, whose field might be sitting in a CPU cache, any other thread that might have a copy of that volatile field in its CPU cache, a different CPU cache than the other thread that performed the change, must have its CPU cache updated before its thread reads that volatile field found in its local CPU cache, or it must be instructed to retrieve the updated volatile field’s value from memory. To ensure CPU caches are updated, that is, kept in sync, in the presence of volatile fields, a CPU instruction, a memory barrier, often called a membar or fence, is emitted to update CPU caches with a change in a volatile field’s value.


    Beginning Java 8 Language Features by Kishori Sharan Ch 6 Threads Java Memory Model Page no 186 wrote:A write to a volatile variable is always written to the main memory. A read on a volatile variable is always read from the main memory. That is, a volatile variable is never cached in the working memory of a thread. In effect, any write to a volatile variable is flushed to the main memory, immediately making the new value visible to other threads.


    Java in a Nutshell 6th Edition Ch. 3 Page no 102 wrote:The volatile modifier says that the value of a field must always be read from and flushed to main memory, and that it may not be cached by a thread (in a register or CPU cache).


    But It is nowhere mentioned in JLS but mentioned in JVMS 8 4.5
     
    Tim Holloway
    Bartender
    Posts: 18414
    58
    Android Eclipse IDE Linux
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    The "volatile" keyword was actually stolen (like much of Java) from C.

    Originally, C was pretty much dumb line-by-line translated into sets of machine-language instructions. So for example, C = A+B: Load Register 1 with A, Load Register 2 with B, Add Register 2 to Register 1, Store Register 1 to C. Repeat on next instruction. D = Q + B: Load register 1 with Q, load register 3 with B - even though register 2 still had B in it from the previous instruction - you get the idea.

    As compilers got smarter, they realized that if one of the machine registers already had a value that was needed in it, it wasn't necessary to actually reload that value from RAM, so the extra loads got optimized out.

    That's OK in most cases, but then Memory-Mapped I/O became common. In fact, some CPUs (including the Commodore 64's 6502) didn't even have I/O instructions as such. You simply read/wrote to "memory addresses" that were actually attached to the control and data registers of the I/O hardware. This got really popular once high-volume I/O like graphics processors and Network Interface Cards require. At that point, if you had a value in a register and the I/O hardware changed values on you, you ended up with a problem. The data was no longer what you thought it was - a problem that only got worse as second-level caches on CPU chips became popular, effectively expanding the CPU register set to hundreds or thousands of "registers".

    So the "volatile" compiler directive was added. It says, in essence, don't trust what you "know" the value to be, go out and get it again!

    Note that while multi-threading also has issues where a process can modify a variable while another process is running (especially on multi-core CPUs), this isn't quite the same thing as hardware volatility. The "synchronized" keyword ensures serial access (both read and write) to memory for such cases.
     
    • Post Reply Bookmark Topic Watch Topic
    • New Topic
    Boost this thread!