When not to use volatile variable in Java - java

I understand the volatile variables only guarantee visibility and should not be used for atomic/compound operations. However I think I read some where that it can also be used only if one thread is updating the value (in a single operation). Is this correct ?
So if two threads are updating a volatile variable say boolean flag is this thread safe ?

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.

Related

Atomic variables over Volatile

Since Atomic variables are volatile, are there any disadvantages of using always using Atomic variable even if you just need the volatility aspect?
From a concurrency perspective there is no difference between:
final AtomicInteger foo1 = new AtomicInteger();
And
volatile int foo2;
A foo1.get/set is the same as reading of writing to the foo2. Both will provide atomicity, visibility and ordering guarantees. If you look in the code of e.g. AtomicInteger, you will see a volatile int variable.
The primary use-cases for an Atomic is that it is very easy to do read modify write operations like incrementing a counter. And that you have access to more relaxed forms of ordering like getRelease and setAcquire. But you can do the same thing using AtomicFieldReference and VarHandles (although the syntax is less pretty).
One drawback of atomic is extra memory usage and indirection.
A Variable cannot be atomic. There is a clear difference between Atomicity and Volatile nature.
Atomicity: If only one thread can execute a set of instruction at a given time, the operation is called Atomic.
Volatile: A volatile nature ensures visibility. If a thread modify some volatile state the other threads get most recent updated state.
Examples :
volatile boolean flag;
public void flipTheFlag(){
if(flag == true){
flag = false;
}else{
flag = true;
}
}
If multiple threads are working on operation flipTheFlag, the value of flag will be uncertain even though the flag is volatile variable. That's why operation flipTheFlag need to be Atomic. We can make the flipTheFlag operation atomic just by adding keyword 'synchronized'.
When after creation of the final Atomic object different threads use the object to change the internal state, everything works as if volatile.
However there is an extra object instance around. Costs memory and speed performance. It should in this case be constant/effectively final, and its creation should be done before an other thread will have access.
An other aspect - which correctness I actually do not remember from the java reference but did read elsewhere -, is that with several fields, when one field is volatile on its modification also the other fields will be updated for other threads.
Atomic constants (or similar constant arrays of 1 item) still have a mutable state and are sometimes abused to collect aggregated results with a Stream operation which can only access constants. This means Atomic does not imply a multithreading usage.
In x = x + c; (volatile x) you will read the latest x, but after adding c an other thread might change x and you still will assign a stale sum to x. Here atomicity is required. Or if (x > 0) x = c;.
So to answer the question: depending on the brittle context they are somewhat interchangeable. I can see why you prefer Atomic, but there are simple cases where volatile is considerably more performant, especially in fine grained concurrency.
A last remark: I am not totally confident, whether I am entirely correct here.

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?
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.
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.
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?
If two threads are writing without reading the variable first, there is no problem.. it is safe. Problem arises if a thread first reads, then modifies and then writes. What if second thread is also reading at the same time, reads the same old value as the first thread, and modifies it.. and when it writes, it will simply overwrite the first threads update. BOOM.
val i = 1
-> Thread reads 1 -> Threads 2 reads 1 -> Thread 1 does 1 * .2 = 1.2 -> Thread 2 does 1 * .3 = 1.3 -> Thread 1 writes 1.2 back -> Thread 2 cooly overwrites it to 1.3 instead of doing 1.2 * .3

Using volatile keyword with wrapper classes

In a class on Java Concurrency I was advised to use the following code for a counter in a multithreaded application
private volatile int count;
I was asking myself if I could use the volatile keyword with the wrapper class Integer instead of the primitive type int (see below):
private volatile Integer count;
Would it be correct to use the Integer wrapper class in this case?
Actually both versions are poor designs.
From Java Concurrency in Practice p. 39:
...the semantics of volatile are not strong enough to make the increment operation (count++) atomic, unless you can guarantee that the variable is written only from a single thread. (Atomic variables do provide atomic read-modify-write support and can often be used as "better volatile variables")
So I recommend using AtomicInteger
private AtomicInteger count;
Strictly speaking, it would be correct. If one thread sets a new count, every other thread reading it will get the new value.
You will run into issues if two threads write the value at the same time since there is never a guarantee that the value that you last read for the counter is the value when you go to write the counter. For example, if you have two threads and a counter that is starting off at 0.
Thread 1: int temp = count.intValue(); //temp = 0;
Thread 2: int temp = count.intValue(); //temp = 0;
Thread 1: count = new Integer(temp+1); //count = 1;
Thread 2: count = new Integer(temp+1); //count = 1;
As you can see, you incremented the counter twice but the value only increased by 1. The same behavior can occur even if you change the command to
count = new Integer(count.intValue() + 1);
Since the JVM still needs to read in the value, increment it, and write it out, each of which is at least 1 cycle.
To avoid this, either use an AtomicInteger (which does not need to be volatile), as suggested by #chrylis, or use synchronization and/or locks to make sure you never have 2 threads writing the count.
Marking as volatile is only correct if the only thing you are doing outside of a synchronized region is setting or getting the value. ANY attempt at "relative" math (incrementing, decrementing, etc.) is not thread safe. To do any of that sort of work requires either synchronization or use of an AtomictInteger.
The Integer class is immutable, so when the count changes it gets a reference to a new Integer, and the volatile keyword makes sure the new reference is visible across threads.
But if you want the updates to be atomic then using AtomicInteger would be a better choice, because incrementing based on the current value will not be safe otherwise.

AtomicInteger and volatile [duplicate]

This question already has answers here:
What is the difference between atomic / volatile / synchronized?
(7 answers)
Closed 3 years ago.
I know volatile allows for visibility, AtomicInteger allows for atomicity.
So if I use a volatile AtomicInteger, does it mean I don't have to use any more synchronization mechanisms?
Eg.
class A {
private volatile AtomicInteger count;
void someMethod(){
// do something
if(count.get() < 10) {
count.incrementAndGet();
}
}
Is this threadsafe?
I believe that Atomic* actually gives both atomicity and volatility. So when you call (say) AtomicInteger.get(), you're guaranteed to get the latest value. This is documented in the java.util.concurrent.atomic package documentation:
The memory effects for accesses and updates of atomics generally follow the rules for volatiles, as stated in section 17.4 of The Java™ Language Specification.
get has the memory effects of reading a volatile variable.
set has the memory effects of writing (assigning) a volatile variable.
lazySet has the memory effects of writing (assigning) a volatile variable except that it permits reorderings with subsequent (but not previous) memory actions that do not themselves impose reordering constraints with ordinary non-volatile writes. Among other usage contexts, > - lazySet may apply when nulling out, for the sake of garbage collection, a reference that is never accessed again.
weakCompareAndSet atomically reads and conditionally writes a variable but does not create any happens-before orderings, so provides no guarantees with respect to previous or subsequent reads and writes of any variables other than the target of the weakCompareAndSet.
compareAndSet and all other read-and-update operations such as getAndIncrement have the memory effects of both reading and writing volatile variables.
Now if you have
volatile AtomicInteger count;
the volatile part means that each thread will use the latest AtomicInteger reference, and the fact that it's an AtomicInteger means that you'll also see the latest value for that object.
It's not common (IME) to need this - because normally you wouldn't reassign count to refer to a different object. Instead, you'd have:
private final AtomicInteger count = new AtomicInteger();
At that point, the fact that it's a final variable means that all threads will be dealing with the same object - and the fact that it's an Atomic* object means they'll see the latest value within that object.
I'd say no, it's not thread-safe, if you define thread-safe as having the same result under single threaded mode and multithreaded mode. In single threaded mode, the count will never go greater than 10, but in multithreaded mode it can.
The issue is that get and incrementAndGet is atomic but an if is not. Keep in mind that a non-atomic operation can be paused at any time. For example:
count = 9 currently.
Thread A runs if(count.get() <10) and gets true and stopped there.
Thread B runs if(count.get() <10) and gets true too so it runs count.incrementAndGet() and finishes. Now count = 10.
Thread A resumes and runs count.incrementAndGet(), now count = 11 which will never happen in single threaded mode.
If you want to make it thread-safe without using synchronized which is slower, try this implementation instead:
class A{
final AtomicInteger count;
void someMethod(){
// do something
if(count.getAndIncrement() <10){
// safe now
} else count.getAndDecrement(); // rollback so this thread did nothing to count
}
To maintain the original semantics, and support multiple threads, you could do something like:
public class A {
private AtomicInteger count = new AtomicInteger(0);
public void someMethod() {
int i = count.get();
while (i < 10 && !count.compareAndSet(i, i + 1)) {
i = count.get();
}
}
}
This avoids any thread ever seeing count reach 10.
Answer is there in this code
http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b14/java/util/concurrent/atomic/AtomicInteger.java
This is source code of AtomicInteger.
The value is Volatile.
So,AtomicInteger uses Volatile inside.
Your query can be answered in 2 parts, because there are 2 questions in your query :
1)
Referring to Oracle's tutorial documentation for Atomic variables :
https://docs.oracle.com/javase/tutorial/essential/concurrency/atomicvars.html
The java.util.concurrent.atomic package defines classes that support atomic operations on single variables. All classes have get and set methods that work like reads and writes on volatile variables. That is, a set has a happens-before relationship with any subsequent get on the same variable. The atomic compareAndSet method also has these memory consistency features, as do the simple atomic arithmetic methods that apply to integer atomic variables.
So atomic integer does use volatile inside, as other answers here have mentioned. So there's no point in making your atomic integer volatile. You need to synchronize your method.
You should watch John Purcell's free video on Udemy , where he shows the failure of volatile keyword when multiple threads are trying to modify it. Simple and beautiful example.
https://www.udemy.com/course/java-multithreading/learn/lecture/108950#overview
If you change the volatile counter in John's example into an atomic variable, his code is guaranteed to succeed without using sunchronized keyword like he has done in his tutorial
2) Coming to your code :
Say thread 1 kicks into action and "someMethod" does a get and checks for size. It is possible that before getAndIncrement executes(say, by thread 1) , another thread (say thread 2)kicks in and increases the count to 10, and gets out; after which, your thread 1 will resume and increase count to 11. This is erroneous output. This is because your "someMethod" is not protected in anyway from synhronization problems.
I would still recommend you to watch john purcell's videos to see where volatile fails , so that you have a better understanding of the keyword volatile. Replace it with atomicinteger in his example and see the magic.

Is a volatile int in Java thread-safe?

Is a volatile int in Java thread-safe? That is, can it be safely read from and written to without locking?
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.
[...] as in being able to be safely read from and written to without locking?
Yes, a read will always result in the value of the last write, (and both reads and writes are atomic operations).
A volatile read / write introduces a so called happens-before relation in the execution.
From the Java Language Specification Chapter 17: Threads and Locks
A write to a volatile field (§8.3.1.4) happens-before every subsequent read of that field.
In other words, when dealing with volatile variables you don't have to explicitly synchronize (introduce a happens-before relation) using synchronized keyword in order to ensure that the thread gets the latest value written to the variable.
As Jon Skeet points out though, the use of volatile variables are limited, and you should in general consider using classes from the java.util.concurrent package instead.
Access to volatile int in Java will be thread-safe. When I say access I mean the unit operation over it, like volatile_var = 10 or int temp = volatile_var (basically write/read with constant values). Volatile keyword in java ensures two things :
When reading you always get the value in main memory. Generally for optimization purposes JVM use registers or in more general terms local memory foe storing/access variables. So in multi-threaded environment each thread may see different copy of variable. But making it volatile makes sure that write to variable is flushed to main memory and read to it also happens from main memory and hence making sure that thread see at right copy of variable.
Access to the volatile is automatically synchronized. So JVM ensures an ordering while read/write to the variable.
However Jon Skeet mentions rightly that in non atomic operations (volatile_var = volatile + 1) different threads may get unexpected result.
1) If two threads are both reading and writing to a shared variable, then using the volatile keyword for that is not enough. You need to use a synchronized in that case to guarantee that the reading and writing of the variable is atomic. Reading or writing a volatile variable does not block threads reading or writing. For this to happen you must use the synchronized keyword around critical sections.
2) As an alternative to a synchronized block you could also use one of the many atomic data types found in the java.util.concurrent package. For instance, the AtomicLong or AtomicReference or one of the others.
It's thread safe if you have one writer thread and multiple reader threads.
class Foo {
private volatile Helper helper = null;
public Helper getHelper() {
if (helper == null) {
synchronized(this) {
if (helper == null)
helper = new Helper();
}
}
return helper;
}
}
Note : If helper is immutable then no need of volatile keyword.Here singleton will work properly.
In case of counter which is being incremented by multiple threads (reading writing operation) will not give correct answer. This condition is also illustrated by race condition.
public class Counter{
private volatile int i;
public int increment(){
i++;
}
}
NOTE : Here volatile will not help.
Not always.
It's not thread safe if multiple threads are writing and reading the variable. It's thread safe if you have one writer thread and multiple reader threads.
If you are looking for Thread safely, use AtomicXXX classes
A small toolkit of classes that support lock-free thread-safe programming on single variables.
In essence, the classes in this package extend the notion of volatile values, fields, and array elements to those that also provide an atomic conditional update operation of the form:
boolean compareAndSet(expectedValue, updateValue);
Refer to #teto answer in below post:
Volatile boolean vs AtomicBoolean
If a volatile is not dependent on any other volatile variable its thread safe for read operation. In case of write volatile does not guarantee thread safety.
Assume you have a variable i which is volatile and its value is dependent on another volatile variable say j. Now Thread-1 access variable j and increment it and is about to update it in main memory from CPU cache. In case the Thread-2 reads the
variable i before Thread-1 can actually update the j in main memory. The value of i will be as per the old value of j which would be incorrect. Its also called Dirty read.

Categories

Resources