When to Use Volatile With Multi Threading

Java volatile variable, multi threading

Declaring a volatile Java variable means:

  • The value of this variable will never be cached thread-locally: all reads and writes will go straight to "main memory";
  • Access to the variable acts as though it is enclosed in a synchronized block, synchronized on itself.

In other words, the main differences between synchronized and volatile are:

  • a primitive variable may be declared volatile (whereas you can't synchronize on a primitive with synchronized);
  • an 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");
  • a volatile variable that is an object reference may be null (because you're effectively synchronizing on the reference, not the actual object).

more information is: http://javamex.com/tutorials/synchronization_volatile.shtml

Why is volatile not considered useful in multithreaded C or C++ programming?

The problem with volatile in a multithreaded context is that it doesn't provide all the guarantees we need. It does have a few properties we need, but not all of them, so we can't rely on volatile alone.

However, the primitives we'd have to use for the remaining properties also provide the ones that volatile does, so it is effectively unnecessary.

For thread-safe accesses to shared data, we need a guarantee that:

  • the read/write actually happens (that the compiler won't just store the value in a register instead and defer updating main memory until much later)
  • that no reordering takes place. Assume that we use a volatile variable as a flag to indicate whether or not some data is ready to be read. In our code, we simply set the flag after preparing the data, so all looks fine. But what if the instructions are reordered so the flag is set first?

volatile does guarantee the first point. It also guarantees that no reordering occurs between different volatile reads/writes. All volatile memory accesses will occur in the order in which they're specified. That is all we need for what volatile is intended for: manipulating I/O registers or memory-mapped hardware, but it doesn't help us in multithreaded code where the volatile object is often only used to synchronize access to non-volatile data. Those accesses can still be reordered relative to the volatile ones.

The solution to preventing reordering is to use a memory barrier, which indicates both to the compiler and the CPU that no memory access may be reordered across this point. Placing such barriers around our volatile variable access ensures that even non-volatile accesses won't be reordered across the volatile one, allowing us to write thread-safe code.

However, memory barriers also ensure that all pending reads/writes are executed when the barrier is reached, so it effectively gives us everything we need by itself, making volatile unnecessary. We can just remove the volatile qualifier entirely.

Since C++11, atomic variables (std::atomic<T>) give us all of the relevant guarantees.

When exactly do you use the volatile keyword in Java? [duplicate]

You basically use it when you want to let a member variable be accessed by multiple threads but do not need compound atomicity (not sure if this is the right terminology).

class BadExample {
private volatile int counter;

public void hit(){
/* This operation is in fact two operations:
* 1) int tmp = this.counter;
* 2) this.counter = tmp + 1;
* and is thus broken (counter becomes fewer
* than the accurate amount).
*/
counter++;
}
}

the above is a bad example, because you need compound atomicity.

 class BadExampleFixed {
private int counter;

public synchronized void hit(){
/*
* Only one thread performs action (1), (2) at a time
* "atomically", in the sense that other threads can not
* observe the intermediate state between (1) and (2).
* Therefore, the counter will be accurate.
*/
counter++;
}
}

Now to a valid example:

 class GoodExample {
private static volatile int temperature;

//Called by some other thread than main
public static void todaysTemperature(int temp){
// This operation is a single operation, so you
// do not need compound atomicity
temperature = temp;
}

public static void main(String[] args) throws Exception{
while(true){
Thread.sleep(2000);
System.out.println("Today's temperature is "+temperature);
}
}
}

Now, why can't you just use private static int temperature? In fact you can (in the sense that that your program won't blow up or something), but the change to temperature by the other thread may or may not be "visible" to the main thread.

Basically this means that it is even possible that your app. keeps writing Today's temperature is 0 forever if you don't use volatile (in practice, the value tends to become eventually visible. However, you should not risk not using volatile when necessary, since it can lead to nasty bugs (caused by in-completely constructed objects etc.).

If you put volatile keyword on something that doesn't need volatile, it won't affect your code's correctness (i.e. the behaviour will not change). In terms of performance, it will depend on the JVM implementation. In theory you might get a tiny performance degradation because the compiler can't do reordering optimisations, have to invalidate CPU cache etc., but then again the compiler could prove that your field cannot ever be accessed by multiple threads and remove the effect of volatile keyword completely and compile it to identical instructions.

EDIT:

Response to this comment:

Ok, but why can't we make todaysTemperature synchronized and create a synchronized getter for temperature?

You can and it will behave correctly. Anything that you can with volatile can be done with synchronized, but not vice versa. There are two reasons you might prefer volatile if you can:

  1. Less bug prone: This depends on the context, but in many cases using volatile is less prone to concurrency bugs, like blocking while holding the lock, deadlocks etc.
  2. More performant: In most JVM implementations, volatile can have significantly higher throughput and better latency. However in most applications the difference is too small to matter.

Is 'volatile' needed in this multi-threaded C++ code?

You should not depend on volatile to guarantee thread safety, this is because even though the compiler will guarantee that the the variable is always read from memory (and not a register cache), in multi-processor environments a memory barrier will also be required.

Rather use the correct lock around the shared memory. Locks like a Critical Section are often extremely lightweight and in a case of no contention will probably be all implemented userside. They will also contain the necessary memory barriers.

Volatile should only be used for memory mapped IO where multiple reads may return different values. Similarly for memory mapped writes.

Java Threads: Should all shared variables be Volatile ? [duplicate]

To simplify a little:

  • volatile only provides visibility: when you read a volatile variable you get two guarantees: (1) you see the latest write to the variable, even if it was performed in another thread and (2) all the writes before that volatile write are also visible.
  • synchronized gives you visibility AND atomicity - thread observing the actions performed in a synchronized block from a synchronized block using the same monitor will either see all of them or none of them.

So to answer your question, no, if a variable is written to within a synchronized block, you don't need to mark it volatile, provided that you always read that variable from a synchronized block using the same monitor.


Here are a few examples with volatile:

static class TestVolatile {
private int i = 0;
private volatile int v = 0;

void write() {
i = 5;
v = 7;
}

void read() {
//assuming write was called beforehand
print(i); //could be 0 or 5
print(v); //must be 7
print(i); //must be 5
}

void increment() {
i = i + 1; //if two threads call the method concurrently
//i could be incremented by 1 only, not 2: no atomicity
}
}

And a few examples with synchronized:

static class TestSynchronized {
private int i = 0;
private int j = 0;

void write() {
synchronized(this) {
i = 5;
j = 7;
}
}

void read_OK() {
synchronized(this) {
//assuming write was called beforehand
print(i); //must be 5
print(j); //must be 7
print(i); //must be 5
}
}

void read_NOT_OK() {
synchronized(new Object()) { //not the same monitor
//assuming write was called beforehand
print(i); //can be 0 or 5
print(j); //can be 0 or 7
}
}

void increment() {
synchronized(this) {
i = i + 1; //atomicity guarantees that if two threads call the method
//concurrently, i will be incremented twice
}
}
}

What happens if a volatile variable is written from 2 threads?

The keyword volatile is used to ensure that changes to your Object will be seen by other Threads.
This does not enforce, that non-atomic operations on the Object will be performed without an other Thread interfering before the operation is finished.
For enforcing this you will need the keyword synchronized.

When not to use volatile variable in Java

I understand the volatile variables only guarantee visibility and

correct

should not be used for atomic/compound operations.

Actually all the AtomicXxxx classes use volatile. They use it in a safe manner which is the important difference. Not all operations are safe.

I think I read some where that it can also be used only if one thread is updating the value. Is this correct ?

That is one solution. If you have only one writer, using volatile is fine for that field.

Note: it is s common misconception that volatile confers thread safety for any operation which uses it. e.g.

volatile int[] a = { 0 };

a[0]++; // not thread safe even if you have only 1 writer.

This is because writes to a and only a are volatile. Anything which a points to is not also volatile This is no different to final

final int[] a = { 0 };
a = null; // cannot do this
a[0] = 1; // compiles fine, is not final.

I have narrowed down the scenario for you: if two threads are updating a volatile variable say boolean flag (in a single operation e.g. set it to true or false) and without any other form of synchronizatio,n is this thread safe ?

It is only safe if you have one writer, or they are both setting to the same value. For example

flag = true; // ok, provided no thread sets it to false.
flag = !flag; // not ok.

When not to use volatile?

First of all you should not explain concurrency in terms of caches. Since version 2 java memory model is more formal and has weaker requirements. So, it is all about happens-before order.

if you need concurrent access to some variable you have to order writes and reads by happens-before. This is most import thing. Volatile is just one of implementations of this ordering.

So, instead of volatile you can use any operation with happens-before semantic. From JLS:

  • An unlock on a monitor happens-before every subsequent lock on that
    monitor.

  • A call to start() on a thread happens-before any actions in the
    started thread.

  • All actions in a thread happen-before any other thread successfully

    returns from a join() on that thread.

  • The default initialization of any object happens-before any other

    actions (other than default-writes) of a program.



Related Topics



Leave a reply



Submit