Rectangle 27 0

multithreading Difference between volatile and synchronized in Java?


// Declaration
public class SharedLocation {
    static public SomeObject someObject=new SomeObject(); // default object
    }

// Publishing 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.
SharedLocation.someObject=new SomeObject(...); // new object is published

// Using code
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.
MOV EAX,counter
INC EAX
MOV counter,EAX
public void updateCounter() {
    if(counter==1000) { counter=0; }
    else              { counter++; }
    }

"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 expensive (relatively speaking)." . When you say CPU caches, is it the same as Java Stacks local to each thread? or does a thread has its own local version of Heap? Apologize if i am being silly here.

@MarianPadzioch: An increment or decrement is NOT a read or a write, it's a read and a write; it's a read into a register, then a register increment, then a write back to memory. Reads and writes are individually atomic, but multiple such operations are not.

@nishm It's not the same, but it would include the local caches of the threads involved. .

It's important to understand that there are two aspects to thread safety: (1) execution control, and (2) 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.

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.

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.

So, according to the FAQ, not only the actions made since a lock acquisition are made visible after unlock, but all actions made by that thread are made visible. Even actions made before the lock acquisition.

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.

Speaking to your read-update-write question, specifically. Consider the following unsafe code:

Thanks very much! The example with the counter is simple to understand. However, when things get real, it's a bit different.

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.

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.

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.

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:

Note
Rectangle 27 0

multithreading Difference between volatile and synchronized in Java?


read-write-update query
volatile

A good example to use volatile variable : Date variable.

Answer will be same as in first query.

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.

Is it a good idea to use volatile for variables that depend on input?

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.

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.

Note
Rectangle 27 0

multithreading Difference between volatile and synchronized in Java?


int i1;
    int geti1() {return i1;}

    volatile int i2;
    int geti2() {return i2;}

    int i3;
    synchronized int geti3() {return i3;}
  • (Any changes to variables would normally now be written out to "main" memory, but for geti3() we have no changes.)
  • 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).
  • 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 thread releases the lock on the monitor for object this.

-1, Volatile does not acquire a lock, it uses the underlying CPU architecture to ensure visibility across all threads after the write.

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:

It's worth noting that there may be some cases where a lock may be used to guarantee atomicity of writes. E.g. writing a long on a 32 bit platform that doesn't support extended width rights. Intel avoids this by using SSE2 registers (128 bits wide) to handle volatile longs. However, considering a volatile as a lock will likely lead to nasty bugs in your code.

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.

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.

Thank you a lot, very clear. Could you please articulate what happens if iX are references to objects instead of primitives types? Especially references to instances of classes that already provide synchronized methods.

The important semantic shared by locks a volatile variables is that they both provide Happens-Before edges (Java 1.5 and later). Entering a synchronized block, taking out a lock and reading from a volatile are all considered as an "acquire" and the release of a lock, exiting a synchronized block and writing a volatile are all forms of a "release".

There are two differences between volitile and synchronized.

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.

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:

Note
Rectangle 27 0

multithreading Difference between volatile and synchronized in Java?


int i1;
     int geti1() {return i1;}

     volatile int i2;
     int geti2() {return i2;}

     int i3;
     synchronized int geti3() {return i3;}
int i1;
    int geti1() {return i1;}

    volatile int i2;
    int geti2() {return i2;}

    int i3;
    synchronized int geti3() {return i3;}
  • (Any changes to variables would normally now be written out to "main" memory, but for geti3() we have no changes.)
  • 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).
  • 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 thread releases the lock on the monitor for object this.

-1, Volatile does not acquire a lock, it uses the underlying CPU architecture to ensure visibility across all threads after the write.

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:

It's also important to realize that while the five steps in the answer may be what Java does (currently), it is not what the JMM specifically requires; for example, if the CPU supported it, all that is required within a synchronized block is that any variable accessed be read from main memory on first access; similarly, on exiting a synchronized block all that is required is that any variable that was updated since the synchronize started be updated in main memory. In other words, within the synchronize block the code must see fresh values, and any updates must update main memory.

It's worth noting that there may be some cases where a lock may be used to guarantee atomicity of writes. E.g. writing a long on a 32 bit platform that doesn't support extended width rights. Intel avoids this by using SSE2 registers (128 bits wide) to handle volatile longs. However, considering a volatile as a lock will likely lead to nasty bugs in your code.

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.

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.

Thank you a lot, very clear. Could you please articulate what happens if iX are references to objects instead of primitives types? Especially references to instances of classes that already provide synchronized methods.

The important semantic shared by locks a volatile variables is that they both provide Happens-Before edges (Java 1.5 and later). Entering a synchronized block, taking out a lock and reading from a volatile are all considered as an "acquire" and the release of a lock, exiting a synchronized block and writing a volatile are all forms of a "release".

There are two differences between volitile and synchronized.

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.

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:

Note
Rectangle 27 0

multithreading Difference between volatile and synchronized in Java?


int i1;
    int geti1() {return i1;}

    volatile int i2;
    int geti2() {return i2;}

    int i3;
    synchronized int geti3() {return i3;}
  • (Any changes to variables would normally now be written out to "main" memory, but for geti3() we have no changes.)
  • 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).
  • 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 thread releases the lock on the monitor for object this.

-1, Volatile does not acquire a lock, it uses the underlying CPU architecture to ensure visibility across all threads after the write.

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:

It's worth noting that there may be some cases where a lock may be used to guarantee atomicity of writes. E.g. writing a long on a 32 bit platform that doesn't support extended width rights. Intel avoids this by using SSE2 registers (128 bits wide) to handle volatile longs. However, considering a volatile as a lock will likely lead to nasty bugs in your code.

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.

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.

Thank you a lot, very clear. Could you please articulate what happens if iX are references to objects instead of primitives types? Especially references to instances of classes that already provide synchronized methods.

The important semantic shared by locks a volatile variables is that they both provide Happens-Before edges (Java 1.5 and later). Entering a synchronized block, taking out a lock and reading from a volatile are all considered as an "acquire" and the release of a lock, exiting a synchronized block and writing a volatile are all forms of a "release".

There are two differences between volitile and synchronized.

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.

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:

Note
Rectangle 27 0

multithreading Difference between volatile and synchronized in Java?


// Declaration
public class SharedLocation {
    static public SomeObject someObject=new SomeObject(); // default object
    }

// Publishing 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.
SharedLocation.someObject=new SomeObject(...); // new object is published

// Using code
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.
MOV EAX,counter
INC EAX
MOV counter,EAX
public void updateCounter() {
    if(counter==1000) { counter=0; }
    else              { counter++; }
    }

"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 expensive (relatively speaking)." . When you say CPU caches, is it the same as Java Stacks local to each thread? or does a thread has its own local version of Heap? Apologize if i am being silly here.

@MarianPadzioch: An increment or decrement is NOT a read or a write, it's a read and a write; it's a read into a register, then a register increment, then a write back to memory. Reads and writes are individually atomic, but multiple such operations are not.

@nishm It's not the same, but it would include the local caches of the threads involved. .

It's important to understand that there are two aspects to thread safety: (1) execution control, and (2) 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.

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.

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.

So, according to the FAQ, not only the actions made since a lock acquisition are made visible after unlock, but all actions made by that thread are made visible. Even actions made before the lock acquisition.

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.

Speaking to your read-update-write question, specifically. Consider the following unsafe code:

Thanks very much! The example with the counter is simple to understand. However, when things get real, it's a bit different.

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.

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.

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.

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:

Note
Rectangle 27 0

multithreading Difference between volatile and synchronized in Java?


read-write-update query
volatile

A good example to use volatile variable : Date variable.

Answer will be same as in first query.

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.

Is it a good idea to use volatile for variables that depend on input?

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.

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.

Note
Rectangle 27 0

multithreading Difference between volatile and synchronized in Java?


read-write-update query
volatile

A good example to use volatile variable : Date variable.

Answer will be same as in first query.

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.

Is it a good idea to use volatile for variables that depend on input?

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.

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.

Note