memory visibility on lock acquirement - java

Does memory visibility depend on which monitor is used? Lock B is acquired after lock A is released, is it enough for memory visibility?
for example following code:
int state; // shared
// thread A
synchronized (A) {
state += 1;
}
Thread.sleep(10000000);
// thread B
Thread.sleep(1000);
synchronized(B) {
state += 1;
}
threads are started in the same time and thread B sleep time may be arbitrarily high, just to ensure that it is executed after thread A used state variable. Thread A sleep time is used to ensure that thread does not finish before thread B uses state shared variable.
UPDATE
From http://www.ibm.com/developerworks/library/j-jtp03304/
When a thread exits a synchronized block as part of releasing the associated monitor, the JMM requires that the local processor cache be flushed to main memory.
Similarly, as part of acquiring the monitor when entering a synchronized block, local caches are invalidated so that subsequent reads will go directly to main memory and not the local cache.
If this is true then I see no reason for state variable not to be visible to thread B
Further, however they say that monitor should be the same, but it is not implied from aforementioned statements.
This process guarantees that when a variable is written by one thread during a synchronized block protected by a given monitor and read by another thread during a synchronized block protected by the same monitor, the write to the variable will be visible by the reading thread.
It seems that process of local memory flush is not so straightforward as it is described in the first statement and may not happen on every lock release?

Yes, it depends. You can read this doc about this. Relevant section is "17.4.4. Synchronization Order":
An unlock action on monitor m synchronizes-with all subsequent lock actions on m (where "subsequent" is defined according to the synchronization order).
You see, a concrete monitor object m is specified there. If monitors are different, then you are not getting synchronizes-with relationship, hence, you do not get happens-before relationship (from the 17.4.5):
If an action x synchronizes-with a following action y, then we also have hb(x, y).
So, your updates will be performed out of order with possible missing updates.

Does memory visibility depend on which monitor is used? Yes.
Lock B is acquired after lock A is released, is it enough for memory visibility? No.
The two threads have to synchronize on the same monitor in order to see each others' writes. In your example, both threads could see state having the value 1. No matter what sleep intervals you insert. It of course depends on the implementation of the JVM you're using and different JVMs could yield different results. Basically, you have unsynchronized access to a field and that should always be avoided (because it's not deterministic what value state has).
Read more in the excellent chapter on the Memory Model in the Java Specification.

Related

Impact of wait() method on a thread in synchronization block in java

synchronized (lockObject) {
// update some value of the common shared resource
lockObject.wait();
}
As on call of the wait() method, the thread will release the lock, I want to know after releasing the lock does it also update the value in the main memory of the shared resource object or it only updates the value after the execution of the synchronized block.
It is a fallacy to think that due to synchronization (e.g. synchronized or volatile) data needs to be written to main memory. CPU caches on modern CPUs are always coherent due to the cache coherence protocol.
An object.wait causes the thread to release the lock. And as soon as another thread sends a notify, the lock is reacquired. The object.wait has no semantics in the Java memory model; only acquire and release of the lock are relevant.
So in your particular case, if a thread does a wait, it triggers a lock release. If another thread would read that state after acquiring the same lock, then there is a happens-before edge between the thread that did the release of the lock (due to wait) and the thread that acquired the lock. And therefore the second thread is guaranteed to see the changes of the first.
In the JLS 17.4.5 it says
The wait methods of class Object (§17.2.1) have lock and unlock actions associated with them; their happens-before relationships are defined by these associated actions.
Also, from JLS 17.4.4:
An unlock action on monitor m synchronizes-with all subsequent lock actions on m (where "subsequent" is defined according to the synchronization order).
If a thread waits it gives up the lock so that other threads can act. It only makes sense that any changes the thread made before waiting (which triggers an unlock action) should be visible to other threads acquiring the lock.

Does a non-volatile variable need synchronized?

Consider 2 threads and an array int[] values.
The first thread is performing:
synchronized (values) {
values[i] = 58;
}
while the second thread is performing:
if (values[i] == 58) {
}
outside a synchronized block.
If the first thread first performs values[i]= 58, is it guaranteed that if the second threads executes slightly later, that the if of the second thread reads 58 even though the second thread reads values[i] outside a synchronized block?
If the first thread first performs values[i]= 58, is it guaranteed
that if the second threads executes slightly later, that the if of the
second thread reads 58 even though the second thread reads values[i]
outside a synchronized block?
No
Synchronising this way does not stop other threads to perform any operation on the array simultaneously. However, other threads will be prevented to grab a lock on the array.
Aforementioned behavior is not guaranteed. The guarantee of such a "visibility" is actually a subject of happens-before relationship:
The key to avoiding memory consistency errors is understanding the happens-before relationship. This relationship is simply a guarantee that memory writes by one specific statement are visible to another specific statement.
Happens-before relationship (according to JLS) can be achieved as such:
Each action in a thread happens-before every action in that thread that comes later in the program's order.
An unlock (synchronized block or method exit) of a monitor happens-before every subsequent lock (synchronized block or method entry) of that same monitor. And because the happens-before relation is transitive, all actions of a thread prior to unlocking happen-before all actions subsequent to any thread locking that monitor.
A write to a volatile field happens-before every subsequent read of that same field. Writes and reads of volatile fields have similar memory consistency effects as entering and exiting monitors, but do not entail mutual exclusion locking.
A call to start on a thread happens-before any action in the started thread.
All actions in a thread happen-before any other thread successfully returns from a join on that thread.
So, in your particular case, you actually need either synchronization using a shared monitor or AtomicIntegerArray in order to make access to the array thread-safe; volatile modifier won't help as is, because it only affects the variable pointing to the array, not the array's elements (more detailed explanation).

Should a method be synchronized if it access a volatile variable? [duplicate]

I am wondering at the difference between declaring a variable as volatile and always accessing the variable in a synchronized(this) block in Java?
According to this article http://www.javamex.com/tutorials/synchronization_volatile.shtml there is a lot to be said and there are many differences but also some similarities.
I am particularly interested in this piece of info:
...
access to a volatile variable never has the potential to block: we're only ever doing a simple read or write, so unlike a synchronized block we will never hold on to any lock;
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 we're prepared to "miss an update");
What do they mean by read-update-write? Isn't a write also an update or do they simply mean that the update is a write that depends on the read?
Most of all, when is it more suitable to declare variables volatile rather than access them through a synchronized block? Is it a good idea to use volatile for variables that depend on input? For instance, there is a variable called render that is read through the rendering loop and set by a keypress event?
It's important to understand that there are two aspects to thread safety.
execution control, and
memory visibility
The first has to do with controlling when code executes (including the order in which instructions are executed) and whether it can execute concurrently, and the second to do with when the effects in memory of what has been done are visible to other threads. Because each CPU has several levels of cache between it and main memory, threads running on different CPUs or cores can see "memory" differently at any given moment in time because threads are permitted to obtain and work on private copies of main memory.
Using synchronized prevents any other thread from obtaining the monitor (or lock) for the same object, thereby preventing all code blocks protected by synchronization on the same object from executing concurrently. Synchronization also creates a "happens-before" memory barrier, causing a memory visibility constraint such that anything done up to the point some thread releases a lock appears to another thread subsequently acquiring the same lock to have happened before it acquired the lock. In practical terms, on current hardware, this typically causes flushing of the CPU caches when a monitor is acquired and writes to main memory when it is released, both of which are (relatively) expensive.
Using volatile, on the other hand, forces all accesses (read or write) to the volatile variable to occur to main memory, effectively keeping the volatile variable out of CPU caches. This can be useful for some actions where it is simply required that visibility of the variable be correct and order of accesses is not important. Using volatile also changes treatment of long and double to require accesses to them to be atomic; on some (older) hardware this might require locks, though not on modern 64 bit hardware. Under the new (JSR-133) memory model for Java 5+, the semantics of volatile have been strengthened to be almost as strong as synchronized with respect to memory visibility and instruction ordering (see http://www.cs.umd.edu/users/pugh/java/memoryModel/jsr-133-faq.html#volatile). For the purposes of visibility, each access to a volatile field acts like half a synchronization.
Under the new memory model, it is still true that volatile variables cannot be reordered with each other. The difference is that it is now no longer so easy to reorder normal field accesses around them. Writing to a volatile field has the same memory effect as a monitor release, and reading from a volatile field has the same memory effect as a monitor acquire. In effect, because the new memory model places stricter constraints on reordering of volatile field accesses with other field accesses, volatile or not, anything that was visible to thread A when it writes to volatile field f becomes visible to thread B when it reads f.
-- JSR 133 (Java Memory Model) FAQ
So, now both forms of memory barrier (under the current JMM) cause an instruction re-ordering barrier which prevents the compiler or run-time from re-ordering instructions across the barrier. In the old JMM, volatile did not prevent re-ordering. This can be important, because apart from memory barriers the only limitation imposed is that, for any particular thread, the net effect of the code is the same as it would be if the instructions were executed in precisely the order in which they appear in the source.
One use of volatile is for a shared but immutable object is recreated on the fly, with many other threads taking a reference to the object at a particular point in their execution cycle. One needs the other threads to begin using the recreated object once it is published, but does not need the additional overhead of full synchronization and it's attendant contention and cache flushing.
// Declaration
public class SharedLocation {
static public volatile SomeObject someObject=new SomeObject(); // default object
}
// Publishing code
SharedLocation.someObject=new SomeObject(...); // new object is published
// Using code
// Note: do not simply use SharedLocation.someObject.xxx(), since although
// someObject will be internally consistent for xxx(), a subsequent
// call to yyy() might be inconsistent with xxx() if the object was
// replaced in between calls.
private String getError() {
SomeObject myCopy=SharedLocation.someObject; // gets current copy
...
int cod=myCopy.getErrorCode();
String txt=myCopy.getErrorText();
return (cod+" - "+txt);
}
// And so on, with myCopy always in a consistent state within and across calls
// Eventually we will return to the code that gets the current SomeObject.
Speaking to your read-update-write question, specifically. Consider the following unsafe code:
public void updateCounter() {
if(counter==1000) { counter=0; }
else { counter++; }
}
Now, with the updateCounter() method unsynchronized, two threads may enter it at the same time. Among the many permutations of what could happen, one is that thread-1 does the test for counter==1000 and finds it true and is then suspended. Then thread-2 does the same test and also sees it true and is suspended. Then thread-1 resumes and sets counter to 0. Then thread-2 resumes and again sets counter to 0 because it missed the update from thread-1. This can also happen even if thread switching does not occur as I have described, but simply because two different cached copies of counter were present in two different CPU cores and the threads each ran on a separate core. For that matter, one thread could have counter at one value and the other could have counter at some entirely different value just because of caching.
What's important in this example is that the variable counter was read from main memory into cache, updated in cache and only written back to main memory at some indeterminate point later when a memory barrier occurred or when the cache memory was needed for something else. Making the counter volatile is insufficient for thread-safety of this code, because the test for the maximum and the assignments are discrete operations, including the increment which is a set of non-atomic read+increment+write machine instructions, something like:
MOV EAX,counter
INC EAX
MOV counter,EAX
Volatile variables are useful only when all operations performed on them are "atomic", such as my example where a reference to a fully formed object is only read or written (and, indeed, typically it's only written from a single point). Another example would be a volatile array reference backing a copy-on-write list, provided the array was only read by first taking a local copy of the reference to it.
volatile is a field modifier, while synchronized modifies code blocks and methods. So we can specify three variations of a simple accessor using those two keywords:
int i1;
int geti1() {return i1;}
volatile int i2;
int geti2() {return i2;}
int i3;
synchronized int geti3() {return i3;}
geti1() accesses the value currently stored in i1 in the current thread.
Threads can have local copies of variables, and the data does not have to be the same as the data held in other threads.In particular, another thread may have updated i1 in it's thread, but the value in the current thread could be different from that updated value. In fact Java has the idea of a "main" memory, and this is the memory that holds the current "correct" value for variables. Threads can have their own copy of data for variables, and the thread copy can be different from the "main" memory. So in fact, it is possible for the "main" memory to have a value of 1 for i1, for thread1 to have a value of 2 for i1 and for thread2 to have a value of 3 for i1 if thread1 and thread2 have both updated i1 but those updated value has not yet been propagated to "main" memory or other threads.
On the other hand, geti2() effectively accesses the value of i2 from "main" memory. A volatile variable is not allowed to have a local copy of a variable that is different from the value currently held in "main" memory. Effectively, a variable declared volatile must have it's data synchronized across all threads, so that whenever you access or update the variable in any thread, all other threads immediately see the same value. Generally volatile variables have a higher access and update overhead than "plain" variables. Generally threads are allowed to have their own copy of data is for better efficiency.
There are two differences between volitile and synchronized.
Firstly synchronized obtains and releases locks on monitors which can force only one thread at a time to execute a code block. That's the fairly well known aspect to synchronized. But synchronized also synchronizes memory. In fact synchronized synchronizes the whole of thread memory with "main" memory. So executing geti3() does the following:
The thread acquires the lock on the monitor for object this .
The thread memory flushes all its variables, i.e. it has all of its variables effectively read from "main" memory .
The code block is executed (in this case setting the return value to the current value of i3, which may have just been reset from "main" memory).
(Any changes to variables would normally now be written out to "main" memory, but for geti3() we have no changes.)
The thread releases the lock on the monitor for object this.
So where volatile only synchronizes the value of one variable between thread memory and "main" memory, synchronized synchronizes the value of all variables between thread memory and "main" memory, and locks and releases a monitor to boot. Clearly synchronized is likely to have more overhead than volatile.
http://javaexp.blogspot.com/2007/12/difference-between-volatile-and.html
There are 3 main issues with multithreading:
Race Conditions
Caching / stale memory
Compiler and CPU optimisations
volatile can solve 2 & 3, but can't solve 1. synchronized/explicit locks can solve 1, 2 & 3.
Elaboration:
Consider this thread unsafe code:
x++;
While it may look like one operation, it's actually 3: reading the current value of x from memory, adding 1 to it, and saving it back to memory. If few threads try to do it at the same time, the result of the operation is undefined. If x originally was 1, after 2 threads operating the code it may be 2 and it may be 3, depending on which thread completed which part of the operation before control was transferred to the other thread. This is a form of race condition.
Using synchronized on a block of code makes it atomic - meaning it make it as if the 3 operations happen at once, and there's no way for another thread to come in the middle and interfere. So if x was 1, and 2 threads try to preform x++ we know in the end it will be equal to 3. So it solves the race condition problem.
synchronized (this) {
x++; // no problem now
}
Marking x as volatile does not make x++; atomic, so it doesn't solve this problem.
In addition, threads have their own context - i.e. they can cache values from main memory. That means that a few threads can have copies of a variable, but they operate on their working copy without sharing the new state of the variable among other threads.
Consider that on one thread, x = 10;. And somewhat later, in another thread, x = 20;. The change in value of x might not appear in the first thread, because the other thread has saved the new value to its working memory, but hasn't copied it to the main memory. Or that it did copy it to the main memory, but the first thread hasn't updated its working copy. So if now the first thread checks if (x == 20) the answer will be false.
Marking a variable as volatile basically tells all threads to do read and write operations on main memory only. synchronized tells every thread to go update their value from main memory when they enter the block, and flush the result back to main memory when they exit the block.
Note that unlike data races, stale memory is not so easy to (re)produce, as flushes to main memory occur anyway.
The complier and CPU can (without any form of synchronization between threads) treat all code as single threaded. Meaning it can look at some code, that is very meaningful in a multithreading aspect, and treat it as if it’s single threaded, where it’s not so meaningful. So it can look at a code and decide, in sake of optimisation, to reorder it, or even remove parts of it completely, if it doesn’t know that this code is designed to work on multiple threads.
Consider the following code:
boolean b = false;
int x = 10;
void threadA() {
x = 20;
b = true;
}
void threadB() {
if (b) {
System.out.println(x);
}
}
You would think that threadB could only print 20 (or not print anything at all if threadB if-check is executed before setting b to true), as b is set to true only after x is set to 20, but the compiler/CPU might decide to reorder threadA, in that case threadB could also print 10. Marking b as volatile ensures that it won’t be reordered (or discarded in certain cases). Which mean threadB could only print 20 (or nothing at all). Marking the methods as syncrhonized will achieve the same result. Also marking a variable as volatile only ensures that it won’t get reordered, but everything before/after it can still be reordered, so synchronization can be more suited in some scenarios.
Note that before Java 5 New Memory Model, volatile didn’t solve this issue.
synchronized is method level/block level access restriction modifier. It will make sure that one thread owns the lock for critical section. Only the thread,which own a lock can enter synchronized block. If other threads are trying to access this critical section, they have to wait till current owner releases the lock.
volatile is variable access modifier which forces all threads to get latest value of the variable from main memory. No locking is required to access volatile variables. All threads can access volatile variable value at same time.
A good example to use volatile variable : Date variable.
Assume that you have made Date variable volatile. All the threads, which access this variable always get latest data from main memory so that all threads show real (actual) Date value. You don't need different threads showing different time for same variable. All threads should show right Date value.
Have a look at this article for better understanding of volatile concept.
Lawrence Dol cleary explained your read-write-update query.
Regarding your other queries
When is it more suitable to declare variables volatile than access them through synchronized?
You have to use volatile if you think all threads should get actual value of the variable in real time like the example I have explained for Date variable.
Is it a good idea to use volatile for variables that depend on input?
Answer will be same as in first query.
Refer to this article for better understanding.

Java volatile and synchronized

I know that volatile keyword refresh all the invisible data i.e. if some thread read volatile variable all potential invisible variables/references (not only the variable that will be read) will be okey(visible i.e. with correct values) after this reading. Right? But what about synchronized ? Is it the same ? If in synchronized block we read 3 variables for example will all other varibles will be visible?
What will hapen if one thread change the value of some variable (for example set varible "age" from 2 to 33) from non-synchronized block and after this thread die ? The value could be written in the thread stack, but main thread maybe will not see this change, the background thread will die and the new value is gone and can not be retrieved?
And last question if we have 2 background threads and we know that our main thread will be notified (in some way) just before every one of them will die and our thread will wait both of them to finish their work and will continue after that, how we can assure that all variables changes(which are made by the background threads) will be visible to the main thread? We can just put synchronized block after the background thread finishes or ? We don't want to access variables that are changed from the background threads with synchronized blocks every time after this threads are dead (because it's overhead), but we need to have their right values ? But it is unnatural to read some fake volatile variable or to use fake synchronized block(if it refresh all data) just to refresh all data.
I hope that my questions are explained well.
Thanks in advance.
Reading the value of a volatile variable creates a happens-before relationship between the writing from one thread and the reading of another.
See http://jeremymanson.blogspot.co.uk/2008/11/what-volatile-means-in-java.html:
The Java volatile modifier is an example of a special mechanism to
guarantee that communication happens between threads. When one thread
writes to a volatile variable, and another thread sees that write, the
first thread is telling the second about all of the contents of memory
up until it performed the write to that volatile variable.
Synchronized blocks create a happens-before relationship as well. See http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/package-summary.html
An unlock (synchronized block or method exit) of a monitor
happens-before every subsequent lock (synchronized block or method
entry) of that same monitor. And because the happens-before relation
is transitive, all actions of a thread prior to unlocking
happen-before all actions subsequent to any thread locking that
monitor.
Which have the same effect on visibility.
If a value is written without any kind of synchronization then there is no guarantee that other threads will ever see this value. If you want to share values across threads, you should be adding some kind of synchronization or locking, or using volatile.
All your questions are answered in the java.util.concurrent package documentation.
But what about synchronized?
Here's what the documentation says:
An unlock (synchronized block or method exit) of a monitor happens-before every subsequent lock (synchronized block or method entry) of that same monitor. And because the happens-before relation is transitive, all actions of a thread prior to unlocking happen-before all actions subsequent to any thread locking that monitor.
.
The value could be written in the thread stack, but main thread maybe will not see this change, the background thread will die and the new value is gone and can not be retrieved?
If the value is written in the thread stack, then we're talking about a local variable. Local variable are not accessible anywhere except in the method declaring that variable. So if the thread dies, of course the stack doesn't exist and the local variable doesn't exist either. If you're talking about a field of an object, that's stored on the heap. If no other thread has a reference to this object, and if the reference is unreachable from any static variable, then it will be garbage collected.
and our thread will wait both of them to finish their work and will continue after that, how we can assure that all variables changes(which are made by the background threads) will be visible to the main thread
The documentation says:
All actions in a thread happen-before any other thread successfully returns from a join on that thread.
So, since the main thread waits for the background threads to die, it uses join(), and every action made by the background threads will be visible by the main thread after join() returns.
Fully covering the whole topic from the level your question seems to imply will require more than a StackOverflow.com answer, so I recommend looking for a good book on multi threading programming.
volatile guarantee that the read and write accesses to the qualified variable are totally ordered with respect to other accesses to the samevolatile variable1.
It does this by preventing the volatile read and write accesses to be reorder with previous or future instructions and enforcing that all the side effects before the access of the writing thread are visible to a reading thread.
This means that volatile variable are read and written as you see in your code and like the instructions were executed one at a time, beginning the next one only when all the side effects of the previous are completed and visible to every other thread.
To better understand what this means and why this is necessary, look at this question of mine on difference between Memory Barriers and lock prefixed instruction.
Note that volatile in Java is much much much stronger than volatile in C or C++. It does guarantee more that the usual treating of read/write access as a side effect with regard to optimization purposes. This means that is doesn't simply imply that the variable is read from the memory every time, a Java volatile is a memory barrier.
The synchronized block simply guarantees exclusive (i.e. one thread at a time) execution of a block of code.
It doesn't imply that all the thread see the memory access is the same order, a thread could see first the write to a protected shared data structure and then the write to the lock!
1 In some circumstances, where a full memory barrier is emitted, this may enforce that writes and reads to all volatile variables made by a thread T will be visible to other threads in T program order. Note that this not suffices for synchronization as there is still no relationship between inter-thread accesses.
No.
Shared vars are not on the stack of any thread, copy of their value can be but the variables exists independently of any thread.
When a thread dies gracefully, the write is done and can be retrieved (beware of memory ordering again).
If the thread dies forcefully, it could be interrupted anywhere. In any way the actual Java assignment is implemented if the thread stops before the write to the shaded var (by direct assignment or by copying a local value on the stack) then the write never happened.
You don't need synchronized, just volatile as the main thread only reads and the background threads only write (different vars).

Difference between volatile and synchronized in Java

I am wondering at the difference between declaring a variable as volatile and always accessing the variable in a synchronized(this) block in Java?
According to this article http://www.javamex.com/tutorials/synchronization_volatile.shtml there is a lot to be said and there are many differences but also some similarities.
I am particularly interested in this piece of info:
...
access to a volatile variable never has the potential to block: we're only ever doing a simple read or write, so unlike a synchronized block we will never hold on to any lock;
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 we're prepared to "miss an update");
What do they mean by read-update-write? Isn't a write also an update or do they simply mean that the update is a write that depends on the read?
Most of all, when is it more suitable to declare variables volatile rather than access them through a synchronized block? Is it a good idea to use volatile for variables that depend on input? For instance, there is a variable called render that is read through the rendering loop and set by a keypress event?
It's important to understand that there are two aspects to thread safety.
execution control, and
memory visibility
The first has to do with controlling when code executes (including the order in which instructions are executed) and whether it can execute concurrently, and the second to do with when the effects in memory of what has been done are visible to other threads. Because each CPU has several levels of cache between it and main memory, threads running on different CPUs or cores can see "memory" differently at any given moment in time because threads are permitted to obtain and work on private copies of main memory.
Using synchronized prevents any other thread from obtaining the monitor (or lock) for the same object, thereby preventing all code blocks protected by synchronization on the same object from executing concurrently. Synchronization also creates a "happens-before" memory barrier, causing a memory visibility constraint such that anything done up to the point some thread releases a lock appears to another thread subsequently acquiring the same lock to have happened before it acquired the lock. In practical terms, on current hardware, this typically causes flushing of the CPU caches when a monitor is acquired and writes to main memory when it is released, both of which are (relatively) expensive.
Using volatile, on the other hand, forces all accesses (read or write) to the volatile variable to occur to main memory, effectively keeping the volatile variable out of CPU caches. This can be useful for some actions where it is simply required that visibility of the variable be correct and order of accesses is not important. Using volatile also changes treatment of long and double to require accesses to them to be atomic; on some (older) hardware this might require locks, though not on modern 64 bit hardware. Under the new (JSR-133) memory model for Java 5+, the semantics of volatile have been strengthened to be almost as strong as synchronized with respect to memory visibility and instruction ordering (see http://www.cs.umd.edu/users/pugh/java/memoryModel/jsr-133-faq.html#volatile). For the purposes of visibility, each access to a volatile field acts like half a synchronization.
Under the new memory model, it is still true that volatile variables cannot be reordered with each other. The difference is that it is now no longer so easy to reorder normal field accesses around them. Writing to a volatile field has the same memory effect as a monitor release, and reading from a volatile field has the same memory effect as a monitor acquire. In effect, because the new memory model places stricter constraints on reordering of volatile field accesses with other field accesses, volatile or not, anything that was visible to thread A when it writes to volatile field f becomes visible to thread B when it reads f.
-- JSR 133 (Java Memory Model) FAQ
So, now both forms of memory barrier (under the current JMM) cause an instruction re-ordering barrier which prevents the compiler or run-time from re-ordering instructions across the barrier. In the old JMM, volatile did not prevent re-ordering. This can be important, because apart from memory barriers the only limitation imposed is that, for any particular thread, the net effect of the code is the same as it would be if the instructions were executed in precisely the order in which they appear in the source.
One use of volatile is for a shared but immutable object is recreated on the fly, with many other threads taking a reference to the object at a particular point in their execution cycle. One needs the other threads to begin using the recreated object once it is published, but does not need the additional overhead of full synchronization and it's attendant contention and cache flushing.
// Declaration
public class SharedLocation {
static public volatile SomeObject someObject=new SomeObject(); // default object
}
// Publishing code
SharedLocation.someObject=new SomeObject(...); // new object is published
// Using code
// Note: do not simply use SharedLocation.someObject.xxx(), since although
// someObject will be internally consistent for xxx(), a subsequent
// call to yyy() might be inconsistent with xxx() if the object was
// replaced in between calls.
private String getError() {
SomeObject myCopy=SharedLocation.someObject; // gets current copy
...
int cod=myCopy.getErrorCode();
String txt=myCopy.getErrorText();
return (cod+" - "+txt);
}
// And so on, with myCopy always in a consistent state within and across calls
// Eventually we will return to the code that gets the current SomeObject.
Speaking to your read-update-write question, specifically. Consider the following unsafe code:
public void updateCounter() {
if(counter==1000) { counter=0; }
else { counter++; }
}
Now, with the updateCounter() method unsynchronized, two threads may enter it at the same time. Among the many permutations of what could happen, one is that thread-1 does the test for counter==1000 and finds it true and is then suspended. Then thread-2 does the same test and also sees it true and is suspended. Then thread-1 resumes and sets counter to 0. Then thread-2 resumes and again sets counter to 0 because it missed the update from thread-1. This can also happen even if thread switching does not occur as I have described, but simply because two different cached copies of counter were present in two different CPU cores and the threads each ran on a separate core. For that matter, one thread could have counter at one value and the other could have counter at some entirely different value just because of caching.
What's important in this example is that the variable counter was read from main memory into cache, updated in cache and only written back to main memory at some indeterminate point later when a memory barrier occurred or when the cache memory was needed for something else. Making the counter volatile is insufficient for thread-safety of this code, because the test for the maximum and the assignments are discrete operations, including the increment which is a set of non-atomic read+increment+write machine instructions, something like:
MOV EAX,counter
INC EAX
MOV counter,EAX
Volatile variables are useful only when all operations performed on them are "atomic", such as my example where a reference to a fully formed object is only read or written (and, indeed, typically it's only written from a single point). Another example would be a volatile array reference backing a copy-on-write list, provided the array was only read by first taking a local copy of the reference to it.
volatile is a field modifier, while synchronized modifies code blocks and methods. So we can specify three variations of a simple accessor using those two keywords:
int i1;
int geti1() {return i1;}
volatile int i2;
int geti2() {return i2;}
int i3;
synchronized int geti3() {return i3;}
geti1() accesses the value currently stored in i1 in the current thread.
Threads can have local copies of variables, and the data does not have to be the same as the data held in other threads.In particular, another thread may have updated i1 in it's thread, but the value in the current thread could be different from that updated value. In fact Java has the idea of a "main" memory, and this is the memory that holds the current "correct" value for variables. Threads can have their own copy of data for variables, and the thread copy can be different from the "main" memory. So in fact, it is possible for the "main" memory to have a value of 1 for i1, for thread1 to have a value of 2 for i1 and for thread2 to have a value of 3 for i1 if thread1 and thread2 have both updated i1 but those updated value has not yet been propagated to "main" memory or other threads.
On the other hand, geti2() effectively accesses the value of i2 from "main" memory. A volatile variable is not allowed to have a local copy of a variable that is different from the value currently held in "main" memory. Effectively, a variable declared volatile must have it's data synchronized across all threads, so that whenever you access or update the variable in any thread, all other threads immediately see the same value. Generally volatile variables have a higher access and update overhead than "plain" variables. Generally threads are allowed to have their own copy of data is for better efficiency.
There are two differences between volitile and synchronized.
Firstly synchronized obtains and releases locks on monitors which can force only one thread at a time to execute a code block. That's the fairly well known aspect to synchronized. But synchronized also synchronizes memory. In fact synchronized synchronizes the whole of thread memory with "main" memory. So executing geti3() does the following:
The thread acquires the lock on the monitor for object this .
The thread memory flushes all its variables, i.e. it has all of its variables effectively read from "main" memory .
The code block is executed (in this case setting the return value to the current value of i3, which may have just been reset from "main" memory).
(Any changes to variables would normally now be written out to "main" memory, but for geti3() we have no changes.)
The thread releases the lock on the monitor for object this.
So where volatile only synchronizes the value of one variable between thread memory and "main" memory, synchronized synchronizes the value of all variables between thread memory and "main" memory, and locks and releases a monitor to boot. Clearly synchronized is likely to have more overhead than volatile.
http://javaexp.blogspot.com/2007/12/difference-between-volatile-and.html
There are 3 main issues with multithreading:
Race Conditions
Caching / stale memory
Compiler and CPU optimisations
volatile can solve 2 & 3, but can't solve 1. synchronized/explicit locks can solve 1, 2 & 3.
Elaboration:
Consider this thread unsafe code:
x++;
While it may look like one operation, it's actually 3: reading the current value of x from memory, adding 1 to it, and saving it back to memory. If few threads try to do it at the same time, the result of the operation is undefined. If x originally was 1, after 2 threads operating the code it may be 2 and it may be 3, depending on which thread completed which part of the operation before control was transferred to the other thread. This is a form of race condition.
Using synchronized on a block of code makes it atomic - meaning it make it as if the 3 operations happen at once, and there's no way for another thread to come in the middle and interfere. So if x was 1, and 2 threads try to preform x++ we know in the end it will be equal to 3. So it solves the race condition problem.
synchronized (this) {
x++; // no problem now
}
Marking x as volatile does not make x++; atomic, so it doesn't solve this problem.
In addition, threads have their own context - i.e. they can cache values from main memory. That means that a few threads can have copies of a variable, but they operate on their working copy without sharing the new state of the variable among other threads.
Consider that on one thread, x = 10;. And somewhat later, in another thread, x = 20;. The change in value of x might not appear in the first thread, because the other thread has saved the new value to its working memory, but hasn't copied it to the main memory. Or that it did copy it to the main memory, but the first thread hasn't updated its working copy. So if now the first thread checks if (x == 20) the answer will be false.
Marking a variable as volatile basically tells all threads to do read and write operations on main memory only. synchronized tells every thread to go update their value from main memory when they enter the block, and flush the result back to main memory when they exit the block.
Note that unlike data races, stale memory is not so easy to (re)produce, as flushes to main memory occur anyway.
The complier and CPU can (without any form of synchronization between threads) treat all code as single threaded. Meaning it can look at some code, that is very meaningful in a multithreading aspect, and treat it as if it’s single threaded, where it’s not so meaningful. So it can look at a code and decide, in sake of optimisation, to reorder it, or even remove parts of it completely, if it doesn’t know that this code is designed to work on multiple threads.
Consider the following code:
boolean b = false;
int x = 10;
void threadA() {
x = 20;
b = true;
}
void threadB() {
if (b) {
System.out.println(x);
}
}
You would think that threadB could only print 20 (or not print anything at all if threadB if-check is executed before setting b to true), as b is set to true only after x is set to 20, but the compiler/CPU might decide to reorder threadA, in that case threadB could also print 10. Marking b as volatile ensures that it won’t be reordered (or discarded in certain cases). Which mean threadB could only print 20 (or nothing at all). Marking the methods as syncrhonized will achieve the same result. Also marking a variable as volatile only ensures that it won’t get reordered, but everything before/after it can still be reordered, so synchronization can be more suited in some scenarios.
Note that before Java 5 New Memory Model, volatile didn’t solve this issue.
synchronized is method level/block level access restriction modifier. It will make sure that one thread owns the lock for critical section. Only the thread,which own a lock can enter synchronized block. If other threads are trying to access this critical section, they have to wait till current owner releases the lock.
volatile is variable access modifier which forces all threads to get latest value of the variable from main memory. No locking is required to access volatile variables. All threads can access volatile variable value at same time.
A good example to use volatile variable : Date variable.
Assume that you have made Date variable volatile. All the threads, which access this variable always get latest data from main memory so that all threads show real (actual) Date value. You don't need different threads showing different time for same variable. All threads should show right Date value.
Have a look at this article for better understanding of volatile concept.
Lawrence Dol cleary explained your read-write-update query.
Regarding your other queries
When is it more suitable to declare variables volatile than access them through synchronized?
You have to use volatile if you think all threads should get actual value of the variable in real time like the example I have explained for Date variable.
Is it a good idea to use volatile for variables that depend on input?
Answer will be same as in first query.
Refer to this article for better understanding.

Categories

Resources