Java volatile modifier and synchronized blocks - java

Does a variable that is accessed by multiple threads, but only inside synchronized blocks, need the volatile modifier? If not, why?

You do not need to use volatile inside of synchronized, synchronized already guarantees the correct behavior for local caching of variables when used consistently (on every access).
volatile works on primitive values, and can be a nice shortcut for atomic accesses to a primitive type. Note that the behavior of volatile has changed in JDK 5 from 1.4.
More information can be found here

No. When you work within a synchronized block, all cached variables are synchronized on access, since it creates a memory barrier.
For details, see this comparison (with discussion) of volatile to synchronized.

Blocks that synchronize on the same object (or method) are guaranteed to not be run at the same time. So as long as you synchronize to the same object, your variable will never have concurrent accesses, so it doesn't need special treatment.
If your accesses aren't synchronized, then you have a race condition. Making the variable volatile can be correct for some primitive variables (I defer to other posts for better info on volaitle). If that isn't useful, you almost certainly have a bug.

Related

Can using volatile with "AtomicInteger" guarantees thread safety? [duplicate]

This question already has answers here:
What is the difference between atomic / volatile / synchronized?
(7 answers)
Closed 3 years ago.
Suppose I have
private volatile AtomicInteger atomInt = new AtomicInteger(3);
and in methods my usage is atomInt.incrementAndGet().
Since I am using AtomicInteger, it will avoid "thread interference". And then I am using volatile, so it will guarantee the consistent view of the variable across all threads. Does it mean that I have got complete thread safety or still there are chances of "memory consistency issues"?
I got confused because of usage of "reduce" in tutorial, so it suggests me that there are still chances but I cannot think of it:
Using volatile variables reduces the risk of memory consistency
errors, because any write to a volatile variable establishes a
happens-before relationship with subsequent reads of that same
variable.
And then I am using volatile, so it will guarantee the consistent view of the variable across all threads.
Thread-safety is already guaranteed by atomic variables. volatile is redundant if you won't reassign the variable. You can replace volatile with final here:
private final AtomicInteger atomInt = new AtomicInteger(3);
Does it mean that I have got complete thread safety or still there are chances of "memory consistency issues"?
At this moment, it's absolutely thread-safe. No "memory consistency issues" might happen with the variable. But using proper thread-safe components doesn't mean that the whole class/program is thread-safe. Problems might take place if interactions between them are incorrect.
Using volatile variables reduces the risk of memory consistency errors ...
volatile variables can only guarantee visibility. They don't guarantee atomicity.
As Brian Goetz writes (emphasis mine):
volatile variables are convenient, but they have limitations. The most common use for volatile variables is as a completion, interruption, or status flag. Volatile variables can be used for other kinds of state information, but more care is required when attempting this. For example, 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.
You can use volatile variables only when all the following criteria are met:
Writes to the variable do not depend on its current value, or you can ensure that only a single thread ever updates the value;
The variable does not participate in invariants with other state variables;
Locking is not required for any other reason while the variable is being accessed.
From the docs of the java.util.concurrent.atomic package:
get has the memory effects of reading a volatile variable.
set has the memory effects of writing (assigning) a volatile variable.
Volatile does mean that changes to the variable will be visible. But in this case you shouldn’t be changing the reference held by the variable.
It seems very odd that you’d want to make a reference to an Atomic object volatile. The whole point of the atomicinteger class is to provide a way to access and change an integer value safely. The only reason to make some variable volatile is because you intend to overwrite its value. Why overwrite the reference to the AtomicInteger when you can use its instance methods to update its value?
That’s why you are getting advice to make this variable final instead of volatile. Making the variable final nails down the reference so it can’t change, while making sure the reference contained by that variable is visible. The atomicInteger manages its own state in a threadsafe way so you shouldn’t have to overwrite the reference to it.
So it’s not exactly correct to say volatile is redundant here. But it is doing something that typically shouldn’t have to be done. Use volatile when you have to change the value contained in the variable. Use final when you shouldn’t be changing the value contained in the variable.

Do I need AtomicInteger inside a synchronized(anyObject) block?

I want to keep track of a position inside a queue that gets modified inside a synchronized block. Therefore I need a counter variable. Normally I would use AtomicInteger but do I need that here?
PriorityBlockingQueue<TfIdfScore> allScores = sharedFeatureNameToScores.get(featureName);
synchronized (allScores) {
AtomicInteger position = positionCounterMap.get(featureName);
position.getAndAdd(1);
// Do other stuff..
}
Or could I use int or Integer as well? Does the synchronized block protect all my actions inside the block?
In this example position and allScores depend on the same featureName.
If you are writing all of the code (and taking appropriate care) then you don't need to to use both synchronized and an atomic type. Just make sure that all operations on a given map and the counters it contains synchronize on the same object while they do that ... and that part of the code should thread-safe.
On the other hand, if you are worried that someone will forget to synchronize, then an atomic type probably won't solve the problem. A better solution is to make sure that the map and the counters well encapsulated, to reduce the scope for mistakes. (If you can reduce the amount of code can access the state, that reduces the number of places you need to check for thread safety.)
Does the synchronized block protect all my actions inside the block?
Not necessarily.
You can still have thread-safety problems if there is other code accessing or updating the data structures, and that code is not synchronizing on the right mutex; e.g. the same allScores instance.
Synchronized is a more strict then atomic or volatile. Thus you have no need to use atomic in synchronized
Synchronized
Synchronized methods enable a simple strategy for preventing thread interference and memory consistency errors: if an object is visible to more than one thread, all reads or writes to that object's variables are done through synchronized methods.
Volatile
volatile field means that variable won't be cached in processors core/threads. Thus you will have only one copy of variable per all cores/threads
atomic
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.
In your code you are using two different object using featureName: sharedFeatureNameToScores and positionCounterMap.
In order to guarantee that your code is thread safe you need to ensure that the modifications to both of them is made using the same lock (synchronized (allScores) in you code). Once you satisfy this requirement there is no need to user AtomicInteger since the synchronized block protects both so the access to positionCounterMap is made in exclusive mode.

static variables in multithreading

I found that declaring a variable as static makes no sense in Multi-Threading. I assume that, this is because of every thread has its own stack. Is this the only reason?
I know that static variables should be used within synchronized block. but why?
static makes no sense in Multi-Threading.
Im afraid you are making the reverse statement. Static variable is a shared resource, which can be used to exchange some information among different threads. And we need to be careful while accessing such a shared resource. Hence, we need to make sure that the access to static variables in multi-threaded environment is synchronized.
every thread has its own stack
This is a correct statement. Each thread has its own stack but they share the process heap. Stack holds only the local variables and not the variables on the heap. Static variables are stored in the PermGen section of the heap and hence the access to them should be well guarded.
Because first part of question is already answered, I will try to answer on second question.
I know that static variables should be used within synchronized block. but why?
Because if you don't use atomic, operations with variables are not atomic. That's why you should block variables while working with them. But in real world, you can use volatile keyword, that will guarantee you, that threads will have actual values of variable.
If you change a variable in a multithreaded environment, the new value may not neccessarily visibile as it might be cached. This is also true for static variables of course. If you don't use a synchronized block you might consider using volatile instead. This will also guaruantee that the various threads get an updated copy, without the need of synchronizing.
Wether volatile is enough four your application depends on your requirements.
Add volatile to your static declaration.
volatile will guarantee any other thread will see the most recent value of the variable. So, with volatile it will make sense.
However, volatile will not guarantee atomicity. If you write to your variable from more than one thread you might want to use atomics or synchronize block.
I think volatile will be fine.

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.

Method call and atomicity

I have a method with a single atomic operation, like this one
int value;
public void setValue(int value) {
this.value = value;
}
then I call it in obvious way, like
foo.setValue(10);
The question is: would it be atomic operation? If no, what atomic operations will be executed? How I can test this at my computer (if I can)?
Yes, the
this.value = value;
operation is atomic. See the Java Language Specification: Threads and Locks.
Note though that threads are allowed to cache their own values of non-volatile variables, so it is not guaranteed that a successive get-operation would yield the last set value.
To get rid of these kind of data races you need to synchronize the access to the variable somehow. This can be done by
making the method synchronized,
by letting the variable be volatile or,
use AtomicInteger from the java.util.concurrent package. (preferred way imo)
It should also be noted that the operation would not be atomic if you changed from int to long or double. Here is a relevant section from the JLS:
17.4 Non-atomic Treatment of double and long
If a double or long variable is not declared volatile, then for the purposes of load, store, read, and write actions they are treated as if they were two variables of 32 bits each: wherever the rules require one of these actions, two such actions are performed, one for each 32-bit half.
Some useful links:
Wikipedia article on the Java Memory Model
Java Language Specification, Interaction with the Memory Model
It is atomic, because it is just a primitive 32 bit value.
Hence when you read it, there is a guarantee that you will see a value set by one of the threads, but you won't know which one it was.
If it was a long, you wouldn't have the same guarantee, although in practice most VM implementations do treat long writes as atomic operations.
This is what the JLS has to say on the issue:
VM implementors are encouraged to avoid splitting their 64-bit values where possible. Programmers are encouraged to declare shared 64-bit values as volatile or synchronize their programs correctly to avoid possible complications.
But with ints you are safe, question is, is this very weak guarantee enough for you? More often than not, the answer is a no.
First of all, assignment to all primitive types (except 64-bit ones) in Java is atomic according to the Java specification. But for instance auto-increment isn't thread-safe, no matter which type you use.
But the real problem with this code is not atomicity, but visibility. If two threads are modifying the value, they might not see the changes made by each other. Use the volatile keyword or, even better, AtomicInteger to guarantee correct synchronization and visibility.
Please note that synchronized keyword also guarantees visibility, which means if some modification happens inside synchronnized block, it is guaranteed that it will be visible by other threads.

Categories

Resources