Java volatile loop - java

I am working on someone's code and came across the equivalent of this:
for (int i = 0; i < someVolatileMember; i++) {
// Removed for SO
}
Where someVolatileMember is defined like this:
private volatile int someVolatileMember;
If some thread, A, is running the for loop and another thread, B, writes to someVolatileMember then I assume the number of iterations to do would change while thread A is running the loop which is not great. I assume this would fix it:
final int someLocalVar = someVolatileMember;
for (int i = 0; i < someLocalVar; i++) {
// Removed for SO
}
My questions are:
Just to confirm that the number of iterations thread A does can be
changed while the for loop is active if thread B modifies
someVolatileMember
That the local non-volatile copy is sufficient to make sure that when
thread A runs the loop thread B cannot change the number of
iterations

Your understanding is correct:
Per the Java Language Specification, the semantics of a volatile field ensure consistency between values seen after updates done between different threads:
The Java programming language provides a second mechanism, volatile fields, that is more convenient than locking for some purposes.
A field may be declared volatile, in which case the Java Memory Model ensures that all threads see a consistent value for the variable (§17.4).
Note that even without the volatile modifier, the loop count is likely to change depending on many factors.
Once a final variable is assigned, its value is never changed so the loop count will not change.

Well first of all that field is private (unless you omitted some methods that actually might alter it)...
That loop is a bit on non-sense, the way it is written and assuming there are methods that actually might alter someVolatileMember; it is so because you might never know when if finishes, or if does at all. That might even turn out to be a much more expensive loop as having a non-volatile field, because volatile means invalidating caches and draining buffers at the CPU level much more often than usual variables.
Your solution to first read a volatile and use that is actually a very common pattern; it's also given birth to a very common anti-pattern too : "check then act"... You read it into a local variable because if it later changes, you don't care - you are working with the freshest copy you had at the moment. So yes, your solution to copy it locally is fine.

There are also performance implications, since the value of volatile is never fetched from the most local cache but additional steps are being taken by the CPU to ensure that modifications are propagated (it could be cache coherence protocols, deferring reads to L3 cache, or reading from RAM). There are also implications to other variables in scope where volatile variable is used (these get synced with main memory too, however i am not demonstrating it here).
Regarding performance, following code:
private static volatile int limit = 1_000_000_000;
public static void main(String[] args) {
long start = System.nanoTime();
for (int i = 0; i < limit; i++ ) {
limit--; //modifying and reading, otherwise compiler will optimise volatile out
}
System.out.println(limit + " took " + (System.nanoTime() - start) / 1_000_000 + "ms");
}
... prints 500000000 took 4384ms
Removing volatile keyword from above will result in output 500000000 took 275ms.

Related

Java - cache coherence between successive parallel streams?

Consider the following piece of code (which isn't quite what it seems at first glance).
static class NumberContainer {
int value = 0;
void increment() {
value++;
}
int getValue() {
return value;
}
}
public static void main(String[] args) {
List<NumberContainer> list = new ArrayList<>();
int numElements = 100000;
for (int i = 0; i < numElements; i++) {
list.add(new NumberContainer());
}
int numIterations = 10000;
for (int j = 0; j < numIterations; j++) {
list.parallelStream().forEach(NumberContainer::increment);
}
list.forEach(container -> {
if (container.getValue() != numIterations) {
System.out.println("Problem!!!");
}
});
}
My question is: In order to be absolutely certain that "Problem!!!" won't be printed, does the "value" variable in the NumberContainer class need to be marked volatile?
Let me explain how I currently understand this.
In the first parallel stream, NumberContainer-123 (say) is incremented by ForkJoinWorker-1 (say). So ForkJoinWorker-1 will have an up-to-date cache of NumberContainer-123.value, which is 1. (Other fork-join workers, however, will have out-of-date caches of NumberContainer-123.value - they will store the value 0. At some point, these other workers' caches will be updated, but this doesn't happen straight away.)
The first parallel stream finishes, but the common fork-join pool worker threads aren't killed. The second parallel stream then starts, using the very same common fork-join pool worker threads.
Suppose, now, that in the second parallel stream, the task of incrementing NumberContainer-123 is assigned to ForkJoinWorker-2 (say). ForkJoinWorker-2 will have its own cached value of NumberContainer-123.value. If a long period of time has elapsed between the first and second increments of NumberContainer-123, then presumably ForkJoinWorker-2's cache of NumberContainer-123.value will be up-to-date, i.e. the value 1 will be stored, and everything is good. But what if the time elapsed between first and second increments if NumberContainer-123 is extremely short? Then perhaps ForkJoinWorker-2's cache of NumberContainer-123.value might be out of date, storing the value 0, causing the code to fail!
Is my description above correct? If so, can anyone please tell me what kind of time delay between the two incrementing operations is required to guarantee cache consistency between the threads? Or if my understanding is wrong, then can someone please tell me what mechanism causes the thread-local caches to be "flushed" in between the first parallel stream and the second parallel stream?
It should not need any delay. By the time you're out of ParallelStream's forEach, all the tasks have finished. That establishes a happens-before relation between the increment and the end of forEach. All the forEach calls are ordered by being called from the same thread, and the check, similarly, happens-after all the forEach calls.
int numIterations = 10000;
for (int j = 0; j < numIterations; j++) {
list.parallelStream().forEach(NumberContainer::increment);
// here, everything is "flushed", i.e. the ForkJoinTask is finished
}
Back to your question about the threads, the trick here is, the threads are irrelevant. The memory model hinges on the happens-before relation, and the fork-join task ensures happens-before relation between the call to forEach and the operation body, and between the operation body and the return from forEach (even if the returned value is Void)
See also Memory visibility in Fork-join
As #erickson mentions in comments,
If you can't establish correctness through happens-before relationships,
no amount of time is "enough." It's not a wall-clock timing issue; you
need to apply the Java memory model correctly.
Moreover, thinking about it in terms of "flushing" the memory is wrong, as there are many more things that can affect you. Flushing, for instance, is trivial: I have not checked, but can bet that there's just a memory barrier on the task completion; but you can get wrong data because the compiler decided to optimise non-volatile reads away (the variable is not volatile, and is not changed in this thread, so it's not going to change, so we can allocate it to a register, et voila), reorder the code in any way allowed by the happens-before relation, etc.
Most importantly, all those optimizations can and will change over time, so even if you went to the generated assembly (which may vary depending on the load pattern) and checked all the memory barriers, it does not guarantee that your code will work unless you can prove that your reads happen-after your writes, in which case Java Memory Model is on your side (assuming there's no bug in JVM).
As for the great pain, it's the very goal of ForkJoinTask to make the synchronization trivial, so enjoy. It was (it seems) done by marking the java.util.concurrent.ForkJoinTask#status volatile, but that's an implementation detail you should not care about or rely upon.

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.

Not sure this usage of volatile makes sense, seems to have the same issue

Reading here:
JLS 8.3.1.4 volatile Fields
Without volatile it says
"then method two could occasionally print a value for j that is greater than the value of i, because the example includes no synchronization and"
class Test {
static volatile int i = 0, j = 0;
static void one() { i++; j++; }
static void two() {
System.out.println("i=" + i + " j=" + j);
}
}
With volatile is says
"It is possible, however, that any given invocation of method two might observe a value for j that is much greater than the value observed for i, because method one might be executed many times between the moment when method two fetches the value of i and the moment when method two fetches the value of j."
In behaves 'properly' with synchornization, but I'm confused as to what benefit volatile brings here?
I thought volatile gaurantees the order is preserved, so I would have thought it SOME cases the value of i might be greater than j, but not the other way around since that implies the order of incrementing was changed.
Is that a typo in the doc? If not, please explain how j could be greater than i when using volatile.
It is saying that in the middle of method two method one could run several and that the value read for j would be higher than the value read for i.
read i
run method 1
run method 1
read j
The volatile variable tells the JIT compiler not to perform any optimizations that could affect the ordering of access to that variable. The writes to the volatile variable are always performed in the memory and never on the cache or cpu registers.
Also two more points:
i++ is not a single operation but three: a) read variable i, b) increment, c) store. This "triple" operation is not atomic, meaning there is not a guarantee that would be completed without some other thread looking into its inconsistent state. If you want to do that look at AtomicInteger#getAndIncrement()
your method one() is not synchronised therefore you can have one thread having completed i++ then the second thread prints and the first thread completes the j++ operation then.
From what I understand, volatile guarantees that different threads will reference the same variable instead of copying it, i.e., if you update a volatile variable in a thread, all others will have this variable update because they all reference the same. A good example of this can be found at Why Volatile Matters.
The thing about method two is that it isn't Atomic. It won't run in only one CPU cycle. You can divide it in different operations like #Sign stated. Even i++ isn't atomic, as it needs to read variable i, incremente it and store it again at i reference in memory.
You got the behavior of volatile right; you just didn't read what you quote carefully:
because method one might be executed many times between the moment
when method two fetches the value of i and the moment when method two
fetches the value of j
The order is preserved in one(), it's that in two(), i is fetched and printed, but in the time it takes to print i both i and j might be incremented many times by calls to one() from other threads and so the printed value for j will be higher than the printed value of i.
volatile makes reading OR writing thread safe/memory consistent. It doesn't make reading AND writing atomic however. Using volatile is only fine if only one thread will ever update it.
I suggest you use AtomicInteger instead.
In "source code order", increments to i happen-before increments to j. So, a thread invoking method one() will always observe that i >= j. But, when other threads observe those variables, they can see things differently.
There are certain events that establish what the JLS calls "synchronization order." It makes sense to talk about these events (and only these events) as "happening before" others. Writing to a volatile variable is one of these. Without using volatile, it doesn't make any sense to say that i is incremented before j; those writes could be re-ordered, and that re-ordering can be observed by other threads.
A better example for what can happen without volatile would be this:
static void oneAndAHalf() { System.out.println("j=" + j + " i=" + i);
Even though j appears to be incremented after i, and j is fetched before i, you could still observe j > i because the removal of volatile would permit the operations in one() to be reordered. Add volatile, and oneAndAHalf() will always show i >= j, as you expect.
If you take away volatile, then method two() could print a value for j that is greater than i for either of two reasons: because operations have been reordered, or because i and j are not treated atomically. The current two() method doesn't unambiguously illustrate the utility of volatile. Add volatile, and you'll get the same output, but the only reason is that the operations are not atomic.
To see a consistent view, where i == j, both methods could be synchronized. This would make the increment to both variables appear to be atomic.

Volatile or synchronized for primitive type?

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."

Categories

Resources