• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Liutauras Vilda
  • Campbell Ritchie
  • Tim Cooke
  • Bear Bibeault
  • Devaka Cooray
Sheriffs:
  • Jeanne Boyarsky
  • Knute Snortum
  • Junilu Lacar
Saloon Keepers:
  • Tim Moores
  • Ganesh Patekar
  • Stephan van Hulst
  • Pete Letkeman
  • Carey Brown
Bartenders:
  • Tim Holloway
  • Ron McLeod
  • Vijitha Kumara

Threads - Race Conditions in OCP Java SE 8 Programmer II Exam Guide (Sierra, Bates, Robson)  RSS feed

 
Greenhorn
Posts: 4
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
On Page 688/689, the book says the race condition could be fixed making getInstance() method synchronized AND the INSTANCE variable volatile:



Then it gives the explanation that the volatile makes sure the check null and create new Show() two steps are considered atomically one step (as they have the same visibility in the main memory by marking them volatile my guess), but is it really needed to use volatile since the getInstance() method is marked synchronized already? Wouldn't the synchronizing block other threads while it is executing so it is already considered thread-safe?

 
Marshal
Posts: 60157
188
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Welcome to the Ranch

The keyword synchronized makes the method behave as if it were a single unit, i.e. it behaves as if it were atomic. The behaviour of a volatile variable is different from being atomic, and different from visibility.
What volatile means is that all assignments must be written to primary memory and all reads of the variable must be from primary memory. Otherwise it would be possible for two threads to access that method simultaneously; whichever thread has to wait for the other and gains access to the synchronized method second may find the value of the variable is only in a register on the chip, or only in the chip's caches and the value in primary memory is still null (i.e. the default value). Assignment to that variable or reading from that variable might be done atomically, but the keyword volatile makes sure that such reads and writes are done to/from the came memory location and status.

Adding discussion to our threads forum.
 
Zhenyang Hua
Greenhorn
Posts: 4
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thanks for the explanation on the volatile keyword.

But with the use of synchronized on the static getInstance() methods, it guarantees no other thread will get the class lock of the Show class, so no other threads will be able to execute anything within the synchronized static getInstance() methods, in this example, wouldn't the volatile be redundant?
 
Enthuware Software Support
Rancher
Posts: 4204
35
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Zhenyang Hua wrote:On Page 688/689, the book says the race condition could be fixed making getInstance() method synchronized AND the INSTANCE variable volatile:



Then it gives the explanation that the volatile makes sure the check null and create new Show() two steps are considered atomically one step (as they have the same visibility in the main memory by marking them volatile my guess), but is it really needed to use volatile since the getInstance() method is marked synchronized already? Wouldn't the synchronizing block other threads while it is executing so it is already considered thread-safe?



No, volatile is not needed in this case. Java memory model ensures that if a variable (irrespective of whether it is declared volatile or not) is accessed only from synchronized blocks (synchronizing on the same lock), then the value written by one thread will be visible to another thread that is trying to read that value.
synchonization and volatile both ensure visibility but synchronization ensures ordering in addition to visibility. volatile is kind of a cheaper alternative to synchronization

This is not a topic that can be explained with all its nuances in a forum post. Since it is an important topic, you may want to go through a good book to understand this. This article also explains it nicely for a start.
 
Zhenyang Hua
Greenhorn
Posts: 4
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thanks! That confirms my thought.
 
Saloon Keeper
Posts: 9254
177
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Paul Anilprem wrote:volatile is kind of a cheaper alternative to synchronization


Strongly disagree. The volatile is not an alternative, because it can't do everything that synchronized does.

Volatile establishes a happens-before relationship between executions of statements the same way synchronized does (referring to reordering of statements and writing and reading from main memory), but its main drawback is that it can't make execution of multiple operations atomic.

In practice, to make a class thread-safe, you almost always need to make multiple operations appear as one single atomic operation. That's why the volatile keyword is almost completely useless.

The only common use case I've found for it is when the variable represents a very simple flag to cancel an operation that's in progress, or to flag that an operation has started or finished. That's because the action of setting or reading the flag is atomic by itself:

In the above code, started, finished and cancelled can be volatile, because reading them in their respective getters is a simple atomic operation, and this is less expensive than making those methods synchronized (or in this example, manipulating the lock object).

Even though started is volatile, we still need to protect it with a lock, because checking whether the operation has already started and changing the variable to reflect that the operation has started need to appear as a single atomic operation, otherwise two threads can determine that the operation hasn't started yet, and both perform the operation at the same time.
 
Paul Anilprem
Enthuware Software Support
Rancher
Posts: 4204
35
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Stephan van Hulst wrote:

Paul Anilprem wrote:volatile is kind of a cheaper alternative to synchronization


The volatile is not an alternative, because it can't do everything that synchronized does.


Two things  - 1. the sentence before the one that you have quoted, says the same thing. synchronize does something in addition to what volatile does. So, when you need just the stuff that is common to both (i.e. visibility), volatile is indeed an alternative and is cheaper.
2. The usage of the phrase "kind of" kind of implies that I don't mean to say that synchronized and volatile are exactly the same

But if you just want to focus on the word "alternative" out of context, then yes, you are right. It is not an alternative.


 
Paul Anilprem
Enthuware Software Support
Rancher
Posts: 4204
35
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Stephan van Hulst wrote:
Volatile establishes a happens-before relationship between executions of statements the same way synchronized does (referring to reordering of statements and writing and reading from main memory), but its main drawback is that it can't make execution of multiple operations atomic.


I wouldn't call it a drawback. There are situations (such as the ones you mentioned) where synchronization is not required. Why would you pay the extra cost incurred by synchronized when all you need is to ensure that updates made by one thread are visible to another?


That's why the volatile keyword is almost completely useless.
The only common use case I've found for it is when the variable represents a very simple flag to cancel an operation that's in progress, or to flag that an operation has started or finished.


This use case is actually quite common Hence, not almost completely useless.

 
author
Sheriff
Posts: 23589
138
C++ Chrome Eclipse IDE Firefox Browser Java jQuery Linux VI Editor Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Stephan van Hulst wrote:
In practice, to make a class thread-safe, you almost always need to make multiple operations appear as one single atomic operation. That's why the volatile keyword is almost completely useless.



Side discussion. I would argue that volatile variables are *not* completely useless. Not even close. Volatile variables are need to configure the JVM to treat memory in a way to allow the CAS (compare and set) operations to work. This (CAS support) was introduced with the Atomic classes of Java 5.  And with the atomic classes, it was possible to implement optimistic locking (ie. lock free) algorithms purely in Java.

Henry

 
Stephan van Hulst
Saloon Keeper
Posts: 9254
177
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Paul, I apologize that I wrongly interpreted what you wrote.

Henry, maybe I should have said that volatile variables are mostly useless in new code, because we have the higher level concurrency library to work with (which sure enough, do work with volatile variables).
 
It is sorta covered in the JavaRanch Style Guide.
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!