Is a Volatile Int in Java Thread-Safe

Is a volatile int in Java thread-safe?

Yes, you can read from it and write to it safely - but you can't do anything compound such as incrementing it safely, as that's a read/modify/write cycle. There's also the matter of how it interacts with access to other variables.

The precise nature of volatile is frankly confusing (see the memory model section of the JLS for more details) - I would personally generally use AtomicInteger instead, as a simpler way of making sure I get it right.

how does the volatile count++ operation be made thread safe

A typical use case could look something like this:

public class Foo implements Runnable {
private volatile int itemsProcessed;

public int getItemsProcessed() { return itemsProcessed; }

@Override
public void run() {
while (true) { //this is just an example so we don't care about stopping
processItem(); //process a single item
itemsProcessed++;
}
}
}

Now others can query your thread's progress without extra synchronization but only the thread itself is allowed to update it. For everyone else the field is read-only.

Without volatile other threads may not see any change to itemProcessed at all, or may even see them in a wacky order, sometimes increasing, sometimes decreasing.


The only time multiple threads are okay to write to a volatile variable without any extra synchronization is if the writes are idempotent (that is, multiple writes have the same effect as a single one). This can be seen in this pattern used to stop a thread:

public class Foo implements Runnable {
private volatile boolean stopped = false;

public void stopProcessing() {
stopped = true;
}

public int getItemsProcessed() { return itemsProcessed; }

@Override
public void run() {
while (!stopped) {
processItem(); //process a single item
}
}
}

Here the only thing other threads can do is set stopped to true. It doesn't matter how many of them do it and in what order, the result will always be the same.

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.

How does volatile make my class thread-safe?

The thread-safety can be expressed like "if the object of the class behaves exactly in the same way in multithreaded environment as in single-threaded environment, then it is thread-safe", or maybe instead "behaves exactly as" we could say "behaves correctly".

In your case correct behavior means that after calling setValue(N), a following getValue() returns N. In case you wouldn't use the volatile modifier, this would be true only in single-threaded environment: if you call setValue(N) on Thread1 then after you call getValue() on Thread2, then it won't necessarily return N. The problem is that Thread1 and Thread2 may be executed on separate CPU cores, and CPU cores usually don't read/write directly the shared memory: the two processors can have separate CPU caches, and the setValue(N) call may modify only the CPU-cached copy of the value member, therefore this change won't be immediately visible for the RAM. Furthermore, even if N is already available in the shared memory, the getValue() may read a cached - but obsolete - value from the second processor cache. Therefore the value change you perform on Thread1 may not be immediately visible on Thread2, so getValue() may return a deprecated value.

The volatile modifier solves it with its following 2 properties:

  • after writing a volatile value it won't only be stored in the CPU cache, but immediately flushed into the shared RAM
  • reading a volatile value will always read it from the memory, never from the CPU cache.


Related Topics



Leave a reply



Submit