• Post Reply Bookmark Topic Watch Topic
  • New Topic

Volatile vs Synchronized  RSS feed

 
Ioanna Katsanou
Ranch Hand
Posts: 131
1
Java Oracle
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hello everyone,

I was reading about synchronized and volatile and still cannot figure out the difference / what does each one do, and in which cases I should use synchronized in a method for example or volatile in a method.

Does anyone here have an explanation about this?


Thanks,
Ioanna
 
Stephan van Hulst
Saloon Keeper
Posts: 7992
143
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
The difference is that access of a volatile member doesn't acquire a lock. With the synchronized keyword, other threads can't access the locked part of your code, called the "critical section". The only thing the volatile keyword does, is make sure that when one thread writes to a field, the change is immediately visible to other threads that read that field.

Which of the two should you use? Probably neither. Since Java 1.5, the standard API includes the high level concurrency API which provides tools to deal with certain problems you often encounter in concurrent programming. These tools include Lock, Condition, CyclicBarrier, CountDownLatch, Semaphore, the various atomic data types, and others.
 
David Simkulette
Ranch Hand
Posts: 67
1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
volatile guarantees that the value of the volatile variable will be visible to all threads so no thread sees a stale version of data. Synchronized means only one thread is permitted to enter and execute the statements within the block guarded by the sychronized block.

 
Tim Holloway
Saloon Keeper
Posts: 18799
74
Android Eclipse IDE Linux
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Sure.

"volatile" was actually first created for the C programming language. It was intended to help the code optimizer by letting it know that there could be other agencies  (hardware or software) that might change the value of the variable. This was especially important for "memory mapped I/O devices", where instead of issuing I/O instructions, you'd access the device like it was a small slice of RAM. Graphics cards and network interfaces were especially fond of doing this, although some CPUs such as the Morotola MC68000 series CPUs didn't even have I/O instructions, so every I/O was memory-mapped.

Without the "volatile" hint, an optimizing compiler might fetch a value once, hold it in register storage, and re-use that register value on later read requests. If the hardware (or another task) had changed the actual memory value, the register value would then be erroneous.

"synchronized" is similar except that there is a gatekeeper attached. Back when dinosaurs roamed the swamps, IBM had what they called "serialization" services (and a lot of grief that caused me when Java used the word for something entirely different!) Serial control meant that only one task could access a resource at a time. The ENQ (enqueue) supervisor service put a claim on the service, and the DEQ (dequeue) service released that claim. If a service was claimed, then if another service attempted an ENQ, it would be placed in a task wait state until the task(s) ahead of it released the service.

In more recent times, an equivalent, but much faster function is done by CPU locks, which are typically a single atomic instruction.

With few exceptions (such as Concurrent Pascal), languages older than Java did not have such a feature built into the language, so they had to explicitly call ENQ/DEQ services. In Java, however, declaring a class, method, or property as "synchronized" automatically adds serial access control to that item. It isn't OS or hardware-level serialization - just control within a single VM, but that's usually sufficient.

So what's the difference between "volatile" and "synchronized" control? Well, for one thing, a volatile object may always be in sync with its backing store, but there's no protection against another task or device modifying the value while the primary task is working with it. When something is synchronized, no other Java thread may modify that resource until the primary thread is done with it. So if you declare something as synchronized, the only time you'd also mark it volatile is if some JVM-external resource could modify the memory while it was under synchronous control.

Conversely, there's no need to make something synchronized if you really do want the instantaneous value of the memory location in question and don't need to wait for other tasks to be polite about it. Usually that's a read-only function like polling the status port on a memory-mapped device.
 
David Simkulette
Ranch Hand
Posts: 67
1
 
Campbell Ritchie
Marshal
Posts: 56570
172
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
That tutorial linked to wrote:. . . Access to the variable acts as though it is enclosed in a synchronized block, synchronized on itself. . . .
Is that correct? Does that mean that thread1 can read the value of a variable and manipulate it and in the meantime thread2 cannot gain access to it? That sounds like a lock, not volatile. Or have I read the tutorial wrongly?
 
David Simkulette
Ranch Hand
Posts: 67
1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Campbell Ritchie wrote:
That tutorial linked to wrote:. . . Access to the variable acts as though it is enclosed in a synchronized block, synchronized on itself. . . .
Is that correct? Does that mean that thread1 can read the value of a variable and manipulate it and in the meantime thread2 cannot gain access to it? That sounds like a lock, not volatile. Or have I read the tutorial wrongly?


No that's wrong. LOL .. sorry should have read it more closely. Let me find a better reference. In the mean time volatile means that no thread will have a cached value of the value of a volatile variable.. you still have to put it in a sync'ed block to make sure it's not simultaneously accessed by two threads.

 
David Simkulette
Ranch Hand
Posts: 67
1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Campbell Ritchie wrote:
That tutorial linked to wrote:. . . Access to the variable acts as though it is enclosed in a synchronized block, synchronized on itself. . . .
Is that correct? Does that mean that thread1 can read the value of a variable and manipulate it and in the meantime thread2 cannot gain access to it? That sounds like a lock, not volatile. Or have I read the tutorial wrongly?


Yes read and wrtite to volatile variables are atomic, so in that sense it's like synchronized access, but I can sync a block and still have unfortunate cached views of a variable's variable  contained therein - cached by other threads.

What it literally does is prevent a thread from caching the value of the variable.. this is authoritative....

https://docs.oracle.com/javase/tutorial/essential/concurrency/atomic.html
 
David Simkulette
Ranch Hand
Posts: 67
1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
variable's value that was....
 
David Simkulette
Ranch Hand
Posts: 67
1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
The confusion comes from the fact that synchronized blocks often contain volatile variables . The point of that is to isolate the code inside the block from the effect of other threads and to make sure that the results of that single thread's execution is forced to be seen byu other threads (by using the volatile keyword).

But I have definetely written code that just directly changes a volatile variable's value outside of a sync'ed block. It's not the most normative case, but it's still correct.
 
Ioanna Katsanou
Ranch Hand
Posts: 131
1
Java Oracle
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thank you everyone for your replies.

What I understood from all the above is that:

Volatile can be thought of as "synchronized lite" and it can only be used to do a subset of the things that synchronized can.
(Found this one in this reference: https://www.ibm.com/developerworks/java/library/j-jtp06197/ )

Also, volatile means that no thread will read a cached value because volatile does not perform a lock, but always the current value is shown.

In OCP by Jeanne Boyarsky and Scott Selikoff, page 81 mentions for the first time the volatile keyword. It states that when using lazy instantiation of a Singleton class, it is better to use volatile than synchronized because we only need this for the first time the method getInstance() is called.
This is the part that I cannot understand. In what way does the volatile guarantee the correct synchronization and what is the exact use here???
Still cannot figure it out..

Quote from the book:
The synchronized implementation of getInstance(), while correctly preventing multiple
singleton objects from being created, has the problem that every single call to this
method will require synchronization. In practice, this can be costly and can impact
performance. Synchronization is only needed the first time that the object is created.

As you may have noticed, we added the volatile modifier to our singleton object. This
keyword prevents a subtle case where the compiler tries to optimize the code such that
that the object is accessed before it is finished being constructed.

This solution is better than our previous version, as it performs the synchronization
step only when the singleton does not exist.
If our singleton is accessed thousands of
times over many hours or days, this means that only the first few calls would require
synchronization, and the rest would not.
 
Stephan van Hulst
Saloon Keeper
Posts: 7992
143
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
That's actually a rather difficult topic. Processors are allowed to reorder instructions as long as the end result is the same for the thread that is executing those instructions. In other words, to the thread that's executing the instructions, it must appear that the instructions were performed in the same order as they appear in the code. However, to other threads it may appear that the instructions were performed in a completely different order. The volatile and synchronized keywords introduce so called "memory barriers". When one thread performs a bunch of instructions and then reaches a memory barrier, and another thread also hits that memory barrier (for instance, by reading a volatile variable that the first thread wrote to), all the instructions that were performed before the first thread hit the memory barrier will appear (to the second thread) to be executed in the correct order as well.

https://en.wikipedia.org/wiki/Memory_barrier
 
David Simkulette
Ranch Hand
Posts: 67
1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
OK I have defintely contributed to your confusion by not considering all the possible contexts my answers could be considered in. So please, let me clean up my mess by being as concise as I can.

volatile-

1) can only be applied to variables, not classes or methods.

2) guarantees that no other thread will see a stale value of the variable; This means when Thread A *finishes* writiing to it, Thread B will see that finished-writing value, however.....

3) ... does not ensure atomicity UNLESS the variable itself has inherently atomic writes which is its most popular use, as far as I have seen.

Single atromic reads and writes are guaranteed (but NOT atomic incrementing, which is a read followed by a write, thus 2 operations) if the variable is one of:

byte,
boolean,
char,
int, 
float,

but NOT 64 bit longs or doubles, (but apparently yes! to their 32-bit versions! see: https://docs.oracle.com/javase/specs/jls/se7/html/jls-17.html#jls-17.7 )

No Object has inherently atomic reads and writes.

So in other words volatile does not, on it's own, provide atomicity but as a practical matter is often used with one of the above mentioned primitives and that combination does form an
{ atomic+no_stale_value_seen}  type contract, which is equivalent to synchronization.


Basically, if you think about your CPU it ( probably ) is actually 4 or more distinct CPUs, each with it's own L1 and L2 caches. So if the variable is cached in L1 or L2 cache on CPU #1 then CPU#4 isn't necessarily going to see it in main memory because the changes are happening on CPU#1's  L2 cache. 

That's the whole point of cache- save yourself from having to write to main memory.

So this is great for spped of execution but doesn't serve us so well when our programs are trying to share a value between those CPUs or between a single CPU and its caches and main memory.

So volatile solves the problem of visibility between all these places a variable's value could be hanging out, changing value. but it doesn't solve the problem of atomicity unless that atomicity is already guaranteed by the data type itself.



 
Ioanna Katsanou
Ranch Hand
Posts: 131
1
Java Oracle
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
OK.

It is a little clearer to me now about in which cases to use volatile.
Although I still cannot understand the following from page 81 of OCP.

In the first case we have this class:



It initiates an instance of the Singleton class and is using synchronized.
The book mentions that it is better to use volatile
So the class forms as follows:




and mentions:

This
keyword prevents a subtle case where the compiler tries to optimize the code such that
that the object is accessed before it is finished being constructed.
This solution is better than our previous version, as it performs the synchronization
step only when the singleton does not exist. If our singleton is accessed thousands of
times over many hours or days, this means that only the first few calls would require
synchronization, and the rest would not.


This is the point that still I cannot get. Since volatile does not ensure atomicity, how can it ensures that the object is accessed after it is finished being constructed??


Thanks and sorry for the long posts..
Ioanna
 
Stephan van Hulst
Saloon Keeper
Posts: 7992
143
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Ioanna Katsanou wrote:Since volatile does not ensure atomicity, how can it ensures that the object is accessed after it is finished being constructed??

It doesn't ensure that the object is accessed before it's finished being constructed, the volatile keyword prevents it.

In pseudo-bytecode, imagine the getInstance() method looks like this:

Now, if two threads access getInstance() at the same time, due to instruction reordering, one thread may view the other thread performing the following list of instructions instead:

Let's say that thread A is executing the first list of instructions, and it sees thread B executing the second list of instructions. It's possible that thread B executed lines 1 and 2 of the second listing before thead A executed line 1 of its own listing, because there's nothing that's making thread A wait for thread B. The result of this code path is that thread A sees 'instance' as having a non-null reference, and it jumps to line 9, which returns 'instance', even though it hasn't been initialized yet. Any code that operates on this uninitialized object may fail disastrously.

How does the volatile keyword fix this? It adds memory barriers, so the pseudo-bytecode actually looks like this:

Now, before thread A checks the value of 'instance', it first reorders the instructions of thread B so they appear in the same order that you see in the actual code, thus preventing that it returns a reference to an uninitialized object. It performs this 'order fixing' operation every time it accesses the volatile variable.

You can see that both the synchronized keyword and the volatile keyword cause 'order fixing' operations to appear. The difference is that the volatile keyword doesn't cause 'wait' and 'wake up' operations to appear.
 
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!