Concerning volatile and synchronized - java

After reading a bunch of questions / articles on this topic there is still one thing unclear to me.
From what I understand (and please correct me if I'm wrong) is that the value of a variable can be cached locally to a thread so if one thread updates the value of that variable this change may not be visible to another thread. The use of volatile then is to essentially force all threads to read the value of the variable from the same location. Furthermore, all literature on this topic states that synchronizing on that variable will have the same effect.
My problem is that nothing that I've read ever explicitly states that synchronizing on a different variable will cause this same behavior but frequently provides a code example stating that in the following two cases the value that is read from the variable will be up to date :
volatile int x;
...
int y = x;
and
final Object lock = new Object();
int x;
...
synchronized(lock) {
int y = x;
}
The question is then: is it the case that synchronizing on any arbitrary variable will force every variable access within the synchronized block to access the most up to date value of that variable?

is it the case that synchronizing on any
arbitrary variable will force every variable access within the
synchronized block to access the most up to date value of that
variable?
You can synchronize on any variable for a read so long as the write of that variable was done under synchronization of the same variable.
In your example, so long as something like the following happens then all writes that occurred prior to the write of x will be visible after subsequent read:
synchronized(lock){
x = 10;
}
So to your earlier point:
...nothing I've read ever explicitly states that synchronizing on a different
variable will cause this same behavior...
That is because it doesn't offer the same behavior. The happens-before relationship occurrs on a few occasions, two important ones in your case are
Write and subsequent read of the same volatile variable
The exit and subsequent enter of a monitor on the same object

There is an enlightening article here where it is mentioned:
In the Java Memory Model a volatile field has a store barrier inserted after a write to it and a load barrier inserted before a read of it. ...
Note that there is nothing specific to what field is being accessed. This means that accessing any volatile field generates a barrier for all cached variables.
Synchronising has similar functionality.

Related

Why the code would be at risk for seeing a partially constructed object?

There is an article about volatile using in ibm,and the explanation confused me,below is a sample in this article and its explanation:
public class BackgroundFloobleLoader {
public volatile Flooble theFlooble;
public void initInBackground() {
// do lots of stuff
theFlooble = new Flooble(); // this is the only write to theFlooble
}
}
public class SomeOtherClass {
public void doWork() {
while (true) {
// do some stuff...
// use the Flooble, but only if it is ready
if (floobleLoader.theFlooble != null)
doSomething(floobleLoader.theFlooble);
}
}
}
Without the theFlooble reference being volatile, the code in doWork() would be at risk for seeing a partially constructed Flooble as it dereferences the theFlooble reference.
How to understand this?Why without volatile,we may use a partially constructed Flooble object?Thanks!
Without the volatile you could see a partially constructed object. E.g. consider this Flooble object.
public class Flooble {
public int x;
public int y;
public Flooble() {
x = 5;
y = 1;
}
}
public class SomeOtherClass {
public void doWork() {
while (true) {
// do some stuff...
// use the Flooble, but only if it is ready
if (floobleLoader.theFlooble != null)
doSomething(floobleLoader.theFlooble);
}
public void doSomething(Flooble flooble) {
System.out.println(flooble.x / flooble.y);
}
}
}
Without volatile the method doSomething is not guaranteed to see the values 5 and 1 for x and y. It could see for instance x == 5 but y == 0, leading to division by zero.
When you execute this operation theFlooble = new Flooble(), three writes occur:
tmpFlooble.x = 5
tmpFlooble.y = 1
theFlooble = tmpFlooble
If these writes happen in this order everything is ok. But without the volatile the compiler is free to reorder these writes and perform them as it wishes. E.g. first point 3 and then points 1 and 2.
This actually happens all the time. The compiler really does reorder the writes. This is done to increase performance.
The error can easily happen in the following way:
Thread A executes initInBackground() method from class BackgroundFloobleLoader. The compiler reorders the writes so before executing the body of Flooble() (where x and y are set), the thread A first executes theFlooble = new Flooble(). Now, theFlooble points to a flooble instance, whose x and y are 0. Before thread A continues, some other thread B executes method doWork() of class SomeOtherClass. This method calls method doSomething(floobleLoader.theFlooble) with the current value of theFlooble. In this method theFlooble.x is divided by theFlooble.y resulting in division by zero. Thread B finishes due to uncaught exception. Thread A continues and sets theFlooble.x = 5 and theFlooble.y = 1.
This scenario of course won't happen on every run, but according to the rules of Java, can happen.
When different threads access your code, any thread can perform modifications on the state of your object, which means that when other threads access it, the state may not be as it should.
From the oracle documentation:
The Java programming language allows threads to access shared
variables. As a rule, to ensure that shared variables are
consistently and reliably updated, a thread should ensure that it has
exclusive use of such variables by obtaining a lock that,
conventionally, enforces mutual exclusion for those shared variables.
The Java programming language provides a second mechanism, volatile
fields, that is more convenient than locking for some purposes.
A field may be declared volatile, in which case the Java Memory Model
ensures that all threads see a consistent value for the variable.
source
Which means the value of this variable will never be cached thread-locally, all reads and writes will go straight to "main memory"
For example picture thread1 and thread2 accessing the object:
Thread1 access the object and stores it in its local cache
Trhead2 modifies the object
Thread1 accesses the object again, but since it is still in its cache, it doesn't access the updated state by thread2.
Look at it from the point of view of the code that does this:
if (floobleLoader.theFlooble != null)
doSomething(floobleLoader.theFlooble);
Clearly, you need a guarantee that all of the writes performed by new Flooble() are visible to this code before theFlooble could possibly test as != null. Nothing in the code without volatile provides this guarantee. So you need a guarantee you don't have. Fail.
Java provides several ways to get the guarantee you need. One is by use of a volatile variable:
... any write to a volatile variable establishes a happens-before relationship with subsequent reads of that same variable. This means that changes to a volatile variable are always visible to other threads. What's more, it also means that when a thread reads a volatile variable, it sees not just the latest change to the volatile, but also the side effects of the code that led up the change. -- Docs
So putting a write to a volatile in one thread and a read to a volatile in the other establishes precisely the happens-before relationship we need.
I doubt there is such a thing as partially constructed objects in Java. Volatile guarantees that every thread will see a constructed object. Since volatile works like a tiny synchronized block on the referenced object you would end up with a NPE if theFlobble == null. Maybe that is what they mean.
Objects encapsulate a lot of things: variables, methods, etc. and these take time to come into existence inside a computer. In Java, if any variable is declared volatile then all reads and writes to it is atomic. So if a variable referencing an object is declared volatile then access to its members is allowed only when it fully loads in your system (how do you read or write to something that isn't there at all?)

Non volatile multi-threaded write which is thread visible

I have a variable that I need to set the value of that I want thread visible. I have no idea what thread is doing the reading a writing.
The variable is only ever set once so by setting it as volatile I prevent the variable value from being read from the CPU cache (or so is my understanding). Write once, read many.
I am unable to get this variable into a constructor to use final.
My rough flow is:
thread 1: set value x
thread 1: fire notification to say x is ready.
thread 2: read x.
My understanding is that I can do the following:
public void setX(int value) {
Object o = new Object();
synchronized(o) {
this.x = value;
}
}
And because of the happens-before principle, the value will be written out to memory. Is that correct?
Don't set it to volatile. As a thumb rule, use volatile if the value of that variable is changing and multiple threads read / write to that variable.In your case you want the reads to be cached. because the value of x won't change. Using volatile will reduce performance In your case, you will just have to ensure that the set() happens before the get() . Which will actually happen because unless someThread notifies the other thread, the other thread will not read the value of x.
PS : I am assuming that the other thread(s) will not read value of x unless notified. Let me know if I got your question wrong.
Synchronizing on the object created in the method is pointless.
How you notify() all reading threads is a question you will need to answer yourself - do you intend to have them wait()ing for this notification?
I would suggest to return null or throw from the getter if the value is not set yet instead...

is a volatile variable synchronized? (java)

Say that I have a private variable and I have a setVariable() method for it which is synchronized, isn't it exactly the same as using volatile modifier?
No. Volatile means the variable isn't cached in any per-thread cache, and its value is always retrieved from main memory when needed. Synchronization means that those per-thread caches will be kept in sync at certain points. In theory, using a volatile variable can come with a great speed penalty if many threads need to read the value of the variable, but it is changed only rarely.
No, calling a synchronized getXXX/setXXX method is not the same as reading/writing to a volatile variable.
Multiple threads can concurrently read from or write to a volatile variable. But only one thread at a time can read from or write to a variable that is guarded by a synchronized block.
volatile variables are not synchronized (at least, not in the way synchronized stuff is synchronized). What volatile does is ensure that a variable is retrieved each time it's used (ie: it prevents certain kinds of optimization), and IIRC that it's read and written in the correct order. This could conceivably emulate some kinds of synchronization, but it can't work the same if your setter has to set more than one thing. (If you set two volatile variables, for example, there will be a point where one is set and the other isn't.)
Actually No.
volatile is actually weaker form of synchronization, when field is declared as a volatile the compiler and runtime understands that this variable is shared and operations on it shouldn't be reordered with other memory operations. Volatile variable aren't cached in registers or in caches where they are hidden from other processors, so a read of a volatile variable always return a recent write by any thread.
just an example :
First thread run :
while(stopped){
... do something
}
Second thread run :
stopped = true;
it's useful to declare stopped as a volatile boolean for the first thread to have a fresh value of it.
There is no any relation.
Basically
Volatile => it always retrieves parameter's latest value
Synchronized => it serves only 1 thread at the same time

Java concurrency - why doesn't synchronizing a setter (but not a getter) make a class thread-safe? [duplicate]

This question already has answers here:
Closed 12 years ago.
Possible Duplicate:
Thread safety in Java class
I'm reading Java concurrency in Practice, and I've come to an example that puzzles me.
The authors state that this class is not threadsafe
public class MutableInteger {
private int number;
public int getInt() {
return number;
}
public void setInt(int val) {
number = val;
}
}
And they also state that synchronizing only one method (the setter for example) would not do; you have to syncronize both.
My question is: Why? Wouldn't synchronizing the setter just do?
Java has a happens before/happens after memory model. There needs to be some common concurrent construct (e.g. synchronized block/method, lock, volatile, atomic) on both the write path and the read path to trigger this behaviour.
If you synchronize both methods you are creating a lock on the whole object that will be shared by both the read and write threads. The JVM will ensure that any changes that occur on the writing thread that occur before leaving the (synchronized) setInt method will be visible to any reading threads after they enter the (synchronized) getInt method. The JVM will insert the necessary memory barriers to ensure that this will happen.
If only the write method is synchronized then changes to the object may not be visible to any reading thread. This is because there is no point on the read path that the JVM can use to ensure that the reading thread's visible memory (cache's etc.) are in line with the writing thread. Make the getInt method synchronized would provide that.
Note: specifically in this case making the field 'number' volatile would give the correct behaviour as volatile read/write also provides the same memory visibility behaviour in the JVM and the action inside of the setInt method is only an assignment.
It's explained in the book before the sample (page 35):
"Synchronizing only the setter would not be sufficient: threads calling get would still be able to see stale values."
Stale data: When the reader thread examines ready, it may see an out-of-date value. Unless synchronization is used every time a variable is accessed, it is possible to see a stale value for that variable. Worse, staleness is not all-or-nothing: a thread can see an up-to-date value of one variable but a stale value of another variable that was written first.
If you only Synchronize the setter method, you could only guarantee the attribute would not be amended incorrectly, but you could not be sure it is stale value when you try to read the variable.
because number is not volatile, and getInt() is not synchronized, getInt() may return stale values. For more information, read about the java memory model.

Difference between synchronization of field reads and volatile

In a nice article with some concurrency tips, an example was optimized to the following lines:
double getBalance() {
Account acct = verify(name, password);
synchronized(acct) { return acct.balance; }
}
If I understand that correctly, the point of the synchronization is to ensure that the value of acct.balance that are read by this thread is current and that any pending writes to the fields of the object in acct.balance are also written to main memory.
The example made me think a little: wouldn't it be more efficient to just declare acct.balance (i.e. the field balance of class Account) as volatile? It should be more efficient, save you all the synchronize on accesses to acct.balance and would not lock the whole acct object. Am I missing something?
You are correct. volatile provides a visibility guarantee. synchronized provides both a visibility guarantee AND serialisation of protected code sections. For VERY simple situations volatile is enough, however it is easy to get into trouble using volatile instead of synchronisation.
If you were to assume that Account has a way of adjusting its balance then volatile is not good enough
public void add(double amount)
{
balance = balance + amount;
}
Then we have a problem if balance is volatile with no other synchronization. If two threads were to try and call add() together you could have a "missed" update where the following happens
Thread1 - Calls add(100)
Thread2 - Calls add(200)
Thread1 - Read balance (0)
Thread2 - Read balance (0)
Thread1 - Compute new balance (0+100=100)
Thread2 - Compute new balance (0+200=200)
Thread1 - Write balance = 100
Thread2 - Write balance = 200 (WRONG!)
Obviously this is wrong because both threads read the current value and updated independently and then wrote it back (read, compute, write). volatile does not help here so you would need synchronized to ensure one thread completed the entire update before the other thread began.
I general find that if when writing some code I think "can I use volatile instead of synchronized" the answer might well be "yes" but the time/effort of figuring it out for sure and the danger of getting it wrong is not worth the benefit (minor performance).
As an aside a well written Account class would handle all the synch logic internally so callers don't have to worry about it.
Declaring Account as volatile is subjected to following issues and restrictions
1."Since other threads cannot see local variables, declaring local variables volatile is futile." Moreover If you try to declare a volatile variable in a method, you'll get a compiler error in some cases.
double getBalance() {
volatile Account acct = verify(name, password); //Incorrect ..
}
Declaring Account as volatile warns the compiler to fetch them fresh each time, rather than caching them in registers. This also inhibits certain optimizations that assume no other thread will change the values unexpectedly.
If you need synchronized to co-ordinate changes to variables from different threads,
volatile does not guarantee you atomic access,because accessing a volatile variable never holds a lock, it is not suitable for cases where we want to read-update-write as an atomic operation. Unless you are sure that acct = verify(name, password); is single atomic operation, you cannot guarantee excepted results
If variable acct is an object reference, then chances are it may be null .Attempting to synchronize on a null object will throw a NullPointerException using synchronized.
(because you're effectively synchronizing on the reference, not the actual object)
Where as volatile does not complain
Instead you could declare a boolean variable as volatile like here
private volatile boolean someAccountflag;
public void getBalance() {
Account acct;
while (!someAccountflag) {
acct = verify(name, password);
}
}
Note you cannot declare someAccountflag as synchronized, as
you can't synchronize on a primitive with synchronized, synchronized only works with object variables, where as primitive or object variable may be declared volatile
6.Class final static fields doesn't need to be volatile, JVM takes care of this problem. So the someAccountflag need not be even declared volatile if it is a final static
or you could use lazy singleton initialization making Account as a singleton object
and declare it as follows:
private final static AccountSingleton acc_singleton = new AccountSingleton ();
If multiple threads are modifying and accessing the data, synchronized guarantees data consistency among multiple threads .
if single thread is modifying the data and multiple threads try to read the latest value of data, use volatile construct.
But for above code, volatile does not guaranty memory consistency if multiple threds modify balance. AtomicReference with Double type serves your purpose.
Related SE question:
Difference between volatile and synchronized in Java

Categories