Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Consider the snippet from Java Concurrency in Practice-

@ThreadSafe
public class SynchronizedInteger{
    @GuardedBy("this") private int value;

    public synchronized int getValue() {
        return value;
    }

    public synchronized void setValue(int value) {
        this.value = value;
    }
}

An extract from the same book-

A good way to think about volatile variables is to imagine that they behave roughly like the SynchronizedInteger class in Listing above, replacing reads and writes of the volatile variable with calls to get and set. Yet accessing a volatile variable performs no locking and so cannot cause the executing thread to block, making volatile variables a lighter-weight synchronization mechanism than synchronized.

A special case of thread confinement applies to volatile variables. It is safe to perform read-modify-write operations on shared volatile variables as long as you ensure that the volatile variable is only written from a single thread.

So, if you make the instance variable in the above class as volatile and then remove the synchronized keyword, after that suppose there are 3 threads

Thread A & Thread B are writing to the same volatile variable.
Thread C reads the volatile variable.

Since the volatile variable is now written from 2 threads, why is it unsafe to perform read-modify-write operations on this shared volatile variable?

like image 486
Farhan Shirgill Ansari Avatar asked Aug 05 '16 16:08

Farhan Shirgill Ansari


People also ask

What happens when two threads access same variable?

A race condition occurs when two threads access a shared variable at the same time. The first thread reads the variable, and the second thread reads the same value from the variable.

Are volatile variables thread-safe?

Unlike synchronized methods or blocks, it does not make other threads wait while one thread is working on a critical section. Therefore, the volatile keyword does not provide thread safety when non-atomic operations or composite operations are performed on shared variables.

What happens when a variable is declared as volatile?

Volatile is a qualifier that is applied to a variable when it is declared. It tells the compiler that the value of the variable may change at any time-without any action being taken by the code the compiler finds nearby.

What happens to a variable when being incremented by multiple threads at once?

The threads get the same starting value but there is no shared state.


3 Answers

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.

like image 102
garnulf Avatar answered Oct 20 '22 05:10

garnulf


It's because read-modify-write operations on volatile variables are not atomic. v++ is actually something like:

r1 = v;
r2 = r1 + 1;
v = r2;

So if you have two threads performing this operation once each, it could possibly result in the variable being incremented only once, as they both read the old value. That's an example of why it's not safe.

In your example it would be not safe if you removed synchronized, made the field volatile and had two threads calling setValue after some conditional logic based on the return of getValue - the value could have been modified by the other thread.

If you want atomic operations look at the java.util.concurrent.atomic package.

like image 3
Steve M Avatar answered Oct 20 '22 04:10

Steve M


If you write volatile variable from multiple threads without using any synchronized constructs, you are bound to get data inconsistency errors.

Use volatile variables without synchronization in case of single write thread and multiple read threads for atomic operations.

Volatile make sure that variable value is fetched from main memory instead of Thread cache. It's safe to use in case of single write and multiple read operations.

Use Atomic variables or synchronization or Lock API to update and read variables from multiple threads.

Refer to related SE question:

What is meant by "thread-safe" code?

like image 1
Ravindra babu Avatar answered Oct 20 '22 04:10

Ravindra babu