This question already has answers here:
Is there any point in using a volatile long?
(3 answers)
Closed 7 years ago.
I'm trying to learn the terminologies used in multi-threading in Java. So please correct me if I used wrong definition in following text:
My findings from different resources
Atomic action:
According to Java doc:
In programming, an atomic action is one that effectively happens all at once. An atomic action cannot stop in the middle: it either happens completely, or it doesn't happen at all. No side effects of an atomic action are visible until the action is complete.
And that's why reading or writing to long or double variables are not atomic. Because it involves two operations, first 32-bit and the second-32 bit read/write to the variable. Also, from the paragraph above, I understand that if I used synchronized on a method, it will make the method atomic (theoretically speaking).
Volatile variables: Also from Java Doc:
This means that changes to a volatile variable are always visible to other threads. What's more, it also means that when a thread reads a volatile variable, it sees not just the latest change to the volatile, but also the side effects of the code that led up the change.
Now, also according to Effective Java 2nd Edition by Joshua Bloch, consider the following points mentioned in the book about volatile declaration:
Consider the following:
// Broken - requires synchronization!
private static volatile int nextSerialNumber = 0;
public static int generateSerialNumber() {
return nextSerialNumber++;
}
The method’s state
consists of a single atomically accessible field, nextSerialNumber, and all possible
values of this field are legal. Therefore, no synchronization is necessary to protect
its invariants. Still, the method won’t work properly without synchronization.
This is because nextSerialNumber++ is not atomic as it performs read, increment, write.
My summary
So if nextSerialNumber++ is not atomic, and requires synchronize. Then why the following is atomic and doesn't require synchronize?
private static volatile long someNumber = 0;
public static int setNumber(long someNumber) {
return this.someNumber = someNumber;
}
What I don't understand is why using volatile on double or long, makes it atomic?
Because all volatile does is that it makes sure if thread B tried to read a long variable that is being written by thread A, and only 32-bit of it is written by thread A, then when thread B accesses the resource, it would get the 32-bit number that was written by thread A. And that doesn't make it atomic as the definition of the term atomic is explained in Java Doc.
What I don't understand is why using volatile on double or long, makes it atomic?
Without using the volatile keyword, you might read the first 32 bits of a double or long written by one thread, and the other 32 bits written by another thread, called word tearing, and clearly not atomic.
The volatile keyword makes sure that cannot happen. The 64 bit value you read will be a value written by one thread, not some Franken-value that is the result of writes by multiple threads. This is what it means that these types become atomic thanks to the volatile keyword.
The volatile keyword cannot make an operation like x++ atomic, regardless of the type (64 bit or 32 bit), because it's a compound operation (read + increment + write), as opposed to a simple write. The operations involved in a x++ may be interleaved by operations by other threads. The volatile keyword cannot make such compound operations atomic.
So if nextSerialNumber++ is not atomic, and requires synchronize. Then why the following is atomic and doesn't require synchronize?
private static volatile long someNumber = 0;
public static int setNumber(long someNumber) {
return this.someNumber = someNumber;
}
nextSerialNumber++ requires synchronization because it's a compound operation, and therefore not atomic.
this.someNumber = someNumber is atomic thanks to this.someNumber being volatile, and an assignment operation is also atomic, being a single operation. Therefore there is no need to synchronize. Without volatile, this.someNumber could not be written in an atomic way, so synchronization would be necessary.
What I don't understand is why using volatile on double or long, makes it atomic?
Here's why. Using volatile with a double or long makes them atomic because the JLS says so.
The JLS (Section 17.7) states that:
"Writes and reads of volatile long and double values are always atomic."
Note: the JLS is normative. The javadocs are non-normative as far as the language semantics are concerned. Bloch's "Effective Java" is not even a Oracle document - it is merely an (unauthorized) commentary.
Related
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.
private double value;
public synchronized void setValue(double value) {
this.value = value;
}
public double getValue() {
return this.value;
}
In the above example is there any point in making the getter synchronized?
I think its best to cite Java Concurrency in Practice here:
It is a common mistake to assume that synchronization needs to be used only when writing to shared variables; this is simply not true.
For each mutable state variable that may be accessed by more than one
thread, all accesses to that variable must be performed with the same
lock held. In this case, we say that the variable is guarded by that
lock.
In the absence of synchronization, the compiler, processor, and runtime can do some downright weird things to the order in which operations appear to execute. Attempts to reason about the order in which memory actions "must" happen in insufflciently synchronized multithreaded programs will almost certainly be incorrect.
Normally, you don't have to be so careful with primitives, so if this would be an int or a boolean it might be that:
When a thread reads a variable without synchronization, it may see a
stale value, but at least it sees a value that was actually placed
there by some thread rather than some random value.
This, however, is not true for 64-bit operations, for instance on long or double if they are not declared volatile:
The Java Memory Model requires fetch and
store operations to be atomic, but for nonvolatile long and double
variables, the JVM is permitted to treat a 64-bit read or write as two
separate 32-bit operations. If the reads and writes occur in different
threads, it is therefore possible to read a nonvolatile long and get
back the high 32 bits of one value and the low 32 bits of another.
Thus, even if you don't care about stale values, it is not safe to use
shared mutable long and double variables in multithreaded programs
unless they are declared volatile or guarded by a lock.
Let me show you by example what is a legal way for a JIT to compile your code. You write:
while (myBean.getValue() > 1.0) {
// perform some action
Thread.sleep(1);
}
JIT compiles:
if (myBean.getValue() > 1.0)
while (true) {
// perform some action
Thread.sleep(1);
}
In just slightly different scenarios even the Java compiler could prouduce similar bytecode (it would only have to eliminate the possibility of dynamic dispatch to a different getValue). This is a textbook example of hoisting.
Why is this legal? The compiler has the right to assume that the result of myBean.getValue() can never change while executing above code. Without synchronized it is allowed to ignore any actions by other threads.
The reason here is to guard against any other thread updating the value when a thread is reading and thus avoid performing any action on stale value.
Here get method will acquire intrinsic lock on "this" and thus any other thread which might attempt to set/update using setter method will have to wait to acquire lock on "this" to enter the setter method which is already acquired by thread performing get.
This is why its recommended to follow the practice of using same lock when performing any operation on a mutable state.
Making the field volatile will work here as there are no compound statements.
It is important to note that synchronized methods use intrinsic lock which is "this". So get and set both being synchronized means any thread entering the method will have to acquire lock on this.
When performing non atomic 64 bit operations special consideration should be taken. Excerpts from Java Concurrency In Practice could be of help here to understand the situation -
"The Java Memory Model requires fetch and store operations to be atomic, but for non-volatile long and double variables, the JVM is permitted to treat a 64 bit read or write as two separate 32
bit operations. If the reads and writes occur in different threads, it is therefore possible to read a non-volatile long and get back the high 32 bits of one value and the low 32 bits of another. Thus, even if you don't care about stale values, it
is not safe to use shared mutable long and double variables in multi-threaded programs unless they are declared
volatile or guarded by a lock."
Maybe for someone this code looks awful, but it works very well.
private Double value;
public void setValue(Double value){
updateValue(value, true);
}
public Double getValue(){
return updateValue(value, false);
}
private double updateValue(Double value,boolean set){
synchronized(MyClass.class){
if(set)
this.value = value;
return value;
}
}
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? 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.
In Java, assignment is atomic if the size of the variable is less than or equal to 32 bits but is not if more than 32 bits.
What (volatile/synchronized) would be more efficient to use in case of double or long assignment?
Like,
volatile double x = y;
synchronized is not applicable with primitive argument. How do I use synchronized in this case? Of course I don't want to lock my class, so this should not be used.
What are you trying to do? The synchronized and volatile keywords are mechanisms in Java which can be used to ensure that consistent values are observed by different threads reading the same data. In particular they allow you to reason about happens-before relations in your programs.
You simply cannot avoid using one of volatile or synchronized in order to properly access non-final fields in a multi-threaded program. That said, the main reason that you are likely to require synchronized over volatile is the requirement for using atomic compare and set operations (i.e. it will not be any performance consideration). For example, in a multi-threaded program:
volatile int i = 0;
public void foo() {
if (i == 0) i = i + 1;
}
The above code is inherently unsafe, even though the variable's declaration as being volatile means that reads and writes are flushed to main memory - the only safe implementation of such a method would be something like:
int i = 0;
public synchronized void foo() {
if (i == 0) i = i + 1;
}
So which should you prefer? Well, if you have multiple threads modifying a field dependent on that field's value (i.e. compare-and set), then synchronized is the only safe solution.
It's also worth saying: the performance overhead of synchronized is not a problem (in the overwhelming majority of cases). Synchronization-performance issues are usually due to unnecessary code bottlenecks, deadlocks or livelocks and can be mitigated if necessary. Any pure clock-cycles overhead will be dwarfed by other things you application does: file IO, database queries, remoting etc.
If you find locking on the object itself too heavy, then synchronized is the way to go. Prior to Java 1.5 volatile may have been a good choice, but now volatile can have a very large impact by forcing instruction ordering on the method where the assignment happens. Create a separate object (private final Object X_LOCK = new Object();) and synchronize on it when setting or getting the value of that double. This will give you a fine level of control over the locking, which it seems that you need.
In the new concurrency package there are more options, such as AtomicReference which may be a good replacement for volatile if you really need to avoid synchronization.
volatile is certainly the way to go if you are only doing an assignment.
I'm sure you know, but since it was brought up: if you would like to do more complex operations (increment the value for example) you would need to syncrhonize. i++ is never thread safe for any type of variable. You need to synch. i++ and the like since that is actually more than 1 operation.
Not: It was expressed that you could use AtomicDouble but there is currently no AtomicDouble in java.util.concurrent.atomic
If you are doing a multiple operations on x, that requires setting it to a new value at the end, it is possible to do this in a thread safe manner with no locking what so ever, and have it be thread safe, using compare and set. Example:
AtomicLong x = new AtomicLong(SomeValue);
public void doStuff() {
double oldX;
double newX;
do {
oldX = x.get();
newX = calculateNewX(oldX);
} while (!x.compareAndSet
(Double.doubleToLongBits(oldX), Double.doubleToLongBits(newX)));
This works because compareAndSet will see if the value of x has changed since the last time you read it. If x has changed then you are forced to do the computation over again and re-try setting it.
You could of course implement your own AtomicDouble instead of doing these doubleToLongBits conversions. Take a look at AtomicFieldUpdater.
KDSRathore, you can use some explicit locks, or make some dummy Object object = new Object() , on which you synchronize in setter/getter of that double
According to the oracle documentation, you can use volatile to refer to Double object:
volatile Double x = y;
"Writes to and reads of references are always atomic, regardless of whether they are implemented as 32-bit or 64-bit values."