Should a variable be volatile between 2 running threads? - java

Should int a in this case be volatile to guarantee visibilty between threads?
private volatile static int a = 0;
public static void main(String[] args) {
Thread t1 = new Thread(new Runnable() {
#Override
public void run() {
a = 10;
}
});
Thread t2 = new Thread(new Runnable() {
#Override
public void run() {
System.out.println(a);
}
});
t1.start();
t2.start();
}
Output
10

happens-before is clearly defined in the language specification, start by reading that; to begin with.
Then to fully understand what is going on you need to know what Program order is, as well as synchronization order.
To put it very simplified, look at the below:
private volatile static int a = 0;
private static int b = 0;
public static void main(String[] args) {
Thread t1 = new Thread(new Runnable() {
#Override
public void run() {
b = 100;
a = 10;
}
});
Thread t2 = new Thread(new Runnable() {
#Override
public void run() {
if(a == 10){
System.out.println(b);
}
}
});
t1.start();
t2.start();
}
The only guarantee you have is that if, and only if, t2 prints something, it will always be 100. This is because t2 has seen a volatile write to a. That happens because a "happens-before" has been established, from the writing thread to the reading one, and every action done before a = 10 is guaranteed to be visible to the thread that has seen that a being 10.

Could you explain yourself a bit further on "happens-before"?
The most important thing to remember about "happens before" is that it's a transitive relation. That means, if the Java Language Spec (JLS) promises that A "happens before" B, and it promises that B "happens before" C, then you can infer a promise that A "happens before" C.
The JLS says that a write to some volatile variable "happens before" a subsequent read of the same variable.
Well Duh! Sounds obvious, doesn't it?
But it's not obvious because the JLS does not give the same guarantee for a non-volatile variable. If processor A writes the value 7 to a non-volatile int, and then some time later processor B writes 5, the JLS does not guarantee that some long time later, the final value of the variable will be 5. Processor B will see 5 (that's a different "happens before" promise, see below). Processor A could see 5 or 7, and any other processor could see 5 or 7 or whatever value the variable had initially (e.g., 0).
How the volatile promise helps
Suppose we have
volatile boolean flag = false;
/*non-volatile*/ int i = 0;
Suppose thread A does this:
i = 7;
flag = true;
And suppose thread B does this:
if (flag) {
System.out.println(i);
}
else {
System.out.println("Bleah!");
}
Thread B could print "7", or it could print "Bleah!" but because of the "happens before" guarantee, we absolutely know that thread B will never print "0". Why not?
Thread A set i = 7 before it set flag = true. The JLS guarantees that if a single thread executes one statement before it executes a second statement, then the first statment "happens before" the second statement. (That sounds stupendously obvious, but again, it shouldn't. A lot of things having to do with threads are not obvious.)
Thread B tests flag before it prints i. So *IF* thread A previously set flag=true then we know that i must equal 7: Transitivity: i=7 "happens before" flag=true, and the write to volatile flag, IF IT HAPPENED AT ALL, "happens before" a read of the same flag.
IF IT HAPPENED AT ALL
Data Races and Race Conditions
The biggest thing to remember is that when the JLS promises that A "happens before" B, they are not saying that A always actually does happen before B: They are saying that you can depend on that transitive relationship. They are saying that if A actually did happen before B, then all of the things that "happens before" A must also have actually happened before B.
The program can print "Bleah!" because nothing prevents thread B from testing the flag before thread A sets it. Some people call that a "data race." The two threads are "racing" to see which one gets to the flag first, and the outcome of the program depends on which thread wins that race.
When the correctness of a program depends on the outcome of a data race, some of us call that a "race condition," and that's a real headache. There's no guarantee that a program with a race condition won't do the right thing a thousand times during your testing, and then do the wrong thing when it matters most for your customer.

Related

Volatile Java reordering

Firstly let me say that I am aware of this being a fairly common topic here but searching for it I couldn't quite find another question that clarifies the following situation. I am very sorry if this is a possible duplicate but here you go:
I am new to concurrency and have been given the following code in order to answer questions:
a) Why any other output aside from "00" would be possible?
b) How to amend the code so that "00" will ALWAYS print.
boolean flag = false;
void changeVal(int val) {
if(this.flag){
return;
}
this.initialInt = val;
this.flag = true;
}
int initialInt = 1;
class MyThread extends Thread {
public void run(){
changeVal(0);
System.out.print(initialInt);
}
}
void execute() throws Exception{
MyThread t1 = new MyThread();
MyThread t2 = new MyThread();
t1.start(); t2.start(); t1.join(); t2.join();
System.out.println();
}
For a) my answer would be the following: In the absence of any volatile / synchronization construct the compiler could reorder some of the instructions. In particular, "this.initialInt = val;" and "this.flag = true;" could be switched so that this situation could occur: The threads are both started and t1 charges ahead. Given the reordered instructions it first sets flag = true. Now before it reaches the now last statement of "this.initialInt = val;" the other thread jumps in, checks the if-condition and immediately returns thus printing the unchanged initialInt value of 1. Besides this, I believe that without any volatile / synchronization it is not for certain whether t2 might see the assignment performed to initialInt in t1 so it may also print "1" as the default value.
For b) I think that flag could be made volatile. I have learned that when t1 writes to a volatile variable setting flag = true then t2, upon reading out this volatile variable in the if-statement will see any write operations performed before the volatile write, hence initialInt = val, too. Therefore, t2 will already have seen its initialInt value changed to 0 and must always print 0.
This will only work, however, if the use of volatile successfully prevents any reordering as I described in a). I have read about volatile accomplishing such things but I am not sure whether this always works here in the absence of any further synchronized blocks or any such locks. From this answer I have gathered that nothing happening before a volatile store (so this.flag = true) can be reordered as to appear beyond it. In that case initialInt = val could not be moved down and I should be correct, right? Or not ? :)
Thank you so much for your help. I am looking forward to your replies.
This example will alway print 00 , because you do changeVal(0) before the printing .
to mimic the case where 00 might not be printed , you need to move initialInt = 1; to the context of a thread like so :
class MyThread extends Thread {
public void run(){
initialInt = 1;
changeVal(0);
System.out.print(initialInt);
}
}
now you might have a race condition , that sets initialInt back to 1 in thread1 before it is printed in thread2
another alternative that might results in a race-condition but is harder to understand , is switching the order of setting the flag and setting the value
void changeVal(int val) {
if(this.flag){
return;
}
this.flag = true;
this.initialInt = val;
}
There are no explicit synchronizations, so all kinds of interleavings are possible, and changes made by one thread are not necessarily visible to the other so, it is possible that the changes to flag are visible before the changes to initialInt, causing 10 or 01 output, as well as 00 output. 11 is not possible, because operations performed on variables are visible to the thread performing them, and effects of changeVal(0) will always visible for at least one of the threads.
Making changeVal synchronized, or making flag volatile would fix the issue. flag is the last variable changed in the critical section, so declaring it as volatile would create a happened-before relationship, making changes to initialInt visible.

Understanding happens-before and synchronization [duplicate]

This question already has answers here:
How to understand happens-before consistent
(5 answers)
Closed 4 years ago.
I'm trying to understand Java happens-before order concept and there are a few things that seem very confusing. As far as I can tell, happens before is just an order on the set of actions and does not provide any guarantees about real-time execution order. Actually (emphasize mine):
It should be noted that the presence of a happens-before relationship
between two actions does not necessarily imply that they have to take
place in that order in an implementation. If the reordering produces
results consistent with a legal execution, it is not illegal.
So, all it says is that if there are two actions w (write) and r (read) such that hb(w, r), than r might actually happens before w in an execution, but there's no guarantee that it will. Also the write w is observed by the read r.
How I can determine that two actions are performed subsequently in run-time? For instance:
public volatile int v;
public int c;
Actions:
Thread A
v = 3; //w
Thread B
c = v; //r
Here we have hb(w, r) but that doesn't mean that c will contain value 3 after assignment. How do I enforce that c is assigned with 3? Does synchronization order provide such guarantees?
When the JLS says that some event X in thread A establishes a happens before relationship with event Y in thread B, it does not mean that X will happen before Y.
It means that IF X happens before Y, then both threads will agree that X happened before Y. That is to say, both threads will see the program's memory in a state that is consistent with X happening before Y.
It's all about memory. Threads communicate through shared memory, but when there are multiple CPUs in a system, all trying to access the same memory system, then the memory system becomes a bottleneck. Therefore, the CPUs in a typical multi-CPU computer are allowed to delay, re-order, and cache memory operations in order to speed things up.
That works great when threads are not interacting with one another, but it causes problems when they actually do want to interact: If thread A stores a value into an ordinary variable, Java makes no guarantee about when (or even if) thread B will see the value change.
In order to overcome that problem when it's important, Java gives you certain means of synchronizing threads. That is, getting the threads to agree on the state of the program's memory. The volatile keyword and the synchronized keyword are two means of establishing synchronization between threads.
I think the reason they called it "happens before" is to emphasize the transitive nature of the relationship: If you can prove that A happens before B, and you can prove that B happens before C, then according to the rules specified in the JLS, you have proved that A happens before C.
I would like to associate the above statement with some sample code flow.
To understand this, let us take below class that has two fields counter and isActive.
class StateHolder {
private int counter = 100;
private boolean isActive = false;
public synchronized void resetCounter() {
counter = 0;
isActive = true;
}
public synchronized void printStateWithLock() {
System.out.println("Counter : " + counter);
System.out.println("IsActive : " + isActive);
}
public void printStateWithNoLock() {
System.out.println("Counter : " + counter);
System.out.println("IsActive : " + isActive);
}
}
And assume that there are three thread T1, T2, T3 calling the following methods on the same object of StateHolder:
T1 calls resetCounter() and T2 calls printStateWithLock() at a same time and T1 gets the lock
T3 -> calls printStateWithNoLock() after T1 has completed its execution
It should be noted that the presence of a happens-before relationship between two actions does not necessarily imply that they have to take place in that order in an implementation. If the reordering produces results consistent with a legal execution, it is not illegal.
and the immediate line says,
As per the above statement, it gives the flexibility for JVM, OS or underlying hardware to reorder the statements within the resetCounter() method. And as T1 gets executed it could execute the statements in the below order.
public synchronized void resetCounter() {
isActive = true;
counter = 0;
}
This is inline with the statement not necessarily imply that they have to take place in that order in an implementation.
Now looking at it from a T2 perspective, this reordering doesn't have any negative impact, because both T1 and T2 are synchronizing on the same object and T2 is guaranteed to see changes changes to both of the fields, irrespective of whether the reordering has happened or not, as there is happens-before relationship. So output will always be:
Counter : 0
IsActive : true
This is as per statement, If the reordering produces results consistent with a legal execution, it is not illegal
But look at it from a T3 perspective, with this reordering it possible that T3 will see the updated value of isActive as 'truebut still see thecountervalue as100`, although T1 has completed its execution.
Counter : 100
IsActive : true
The next point in the above link further clarifies the statement and says that:
More specifically, if two actions share a happens-before relationship, they do not necessarily have to appear to have happened in that order to any code with which they do not share a happens-before relationship. Writes in one thread that are in a data race with reads in another thread may, for example, appear to occur out of order to those reads.
In this example T3 has encountered this problem as it doesn't have any happens-before relationship with T1 or T2. This is inline with Not necessarily have to appear to have happened in that order to any code with which they do not share a happens-before relationship.
NOTE: To simplify the case, we have single thread T1 modifying the state and T2 and T3 reading the state. It is possible to have
T1 updates counter to 0, later
T2 modifies isActive to true and sees counter is 0, after sometime
T3 that prints the state could still see only isActive as true but counter is 100, although both T1 and T2 have completed the execution.
As to the last question:
we have hb(w, r) but that doesn't mean that c will contain value 3 after assignment. How do I enforce that c is assigned with 3?
public volatile int v;
public int c;
Thread A
v = 3; //w
Thread B
c = v; //r
Since v is a volatile, as per Happens-before Order
A write to a volatile field (§8.3.1.4) happens-before every subsequent read of that field.
So it is safe to assume that when Thread B tries to read the variable v it will always read the updated value and c will be assigned 3 in the above code.
Interpreting #James' answer to my liking:
// Definition: Some variables
private int first = 1;
private int second = 2;
private int third = 3;
private volatile boolean hasValue = false;
// Thread A
first = 5;
second = 6;
third = 7;
hasValue = true;
// Thread B
System.out.println("Flag is set to : " + hasValue);
System.out.println("First: " + first); // will print 5
System.out.println("Second: " + second); // will print 6
System.out.println("Third: " + third); // will print 7
if you want the state/value of the memory(memory and CPU cache) seen at the
time of a write statement of a variable by one thread,
State of the memory seen by hasValue=true(write statement) in Thread A :
first having value 5,second having value 6,third having value 7
to be seen from every subsequent(why subsequent even though only one
read in Thread B in this example? We many have Thread C doing exactly
similar to Thread B) read statement of the same variable by another
thread,then mark that variable volatile.
If X (hasValue=true) in Thread A happens before Y (sysout(hasValue)) in Thread B, the behaviour should be as if X happened before Y in the same thread (memory values seen at X should be same starting from Y)
Here we have hb(w, r) but that doesn't mean that c will contain value 3 after assignment. How do I enforce that c is assigned with 3? Does synchronization order provide such guarantees?
And your example
public volatile int v;
public int c;
Actions:
Thread A
v = 3; //w
Thread B
c = v; //r
You don't need volatile for v in your example. Let's take a look at a similar example
int v = 0;
int c = 0;
volatile boolean assigned = false;
Actions:
Thread A
v = 3;
assigned = true;
Thread B
while(!assigned);
c = v;
assigned field is volatile.
We will have c = v statement in Thread B only after assigned will be true (while(!assigned) is responsible for that).
if we have volatile — we have happens before.
happens before means that, if we see assigned == true — we will see all that happened before a statement assigned = true: we will see v = 3.
So when we have assigned == true -> we have v = 3.
We have c = 3 as a result.
What will happen without volatile
int v = 0;
int c = 0;
boolean assigned = false;
Actions:
Thread A
v = 3;
assigned = true;
Thread B
while(!assigned);
c = v;
We have assigned without volatile for now.
The value of c in the Thread B can be equal 0 or 3 in such situation. So there is not any guaranties
that c == 3.

Is a runnable with non-final fields unsafe to submit to an executor?

If I have code like the following:
public void foo() {
Executors.newSingleThreadedExecutor().submit(
new Runnable() {
int x = 5;
public void run() {
System.out.println("x = " + x);
}
}
);
}
Am I guaranteed to see "x = 5", or could I also see "x = 0" because the println is being executed in a different thread that might see the uninitialized value of x? I've never witnessed this happen, but I've been unable to find a guarantee that this doesn't happen (for example, if x were final, then it seems it will never happen).
There are a number of "happens before" relationships defined in the latest JMM. One of these points is "starting a thread" and submitting to an executor carries the same guarantees as starting a thread (see the "memory consistency effects" in the javadocs).

Thread value not cached by threads even without volatile?

class Counter
{
public int i=0;
public void increment()
{
i++;
System.out.println("i is "+i);
System.out.println("i/=2 executing");
i=i+22;
System.out.println("i is (after i+22) "+i);
System.out.println("i+=1 executing");
i++;
System.out.println("i is (after i++) "+i);
}
public void decrement()
{
i--;
System.out.println("i is "+i);
System.out.println("i*=2 executing");
i=i*2;
System.out.println("i is after i*2"+i);
System.out.println("i-=1 executing");
i=i-1;
System.out.println("i is after i-1 "+i);
}
public int value()
{
return i;
} }
class ThreadA
{
public ThreadA(final Counter c)
{
new Thread(new Runnable(){
public void run()
{
System.out.println("Thread A trying to increment");
c.increment();
System.out.println("Increment completed "+c.i);
}
}).start();
}
}
class ThreadB
{
public ThreadB(final Counter c)
{
new Thread(new Runnable(){
public void run()
{
System.out.println("Thread B trying to decrement");
c.decrement();
System.out.println("Decrement completed "+c.i);
}
}).start();
}
}
class ThreadInterference
{
public static void main(String args[]) throws Exception
{
Counter c=new Counter();
new ThreadA(c);
new ThreadB(c);
}
}
In the above code, ThreadA first got access to Counter object and incremented the value along with performing some extra operations. For the very first time ThreadA does not have a cached value of i. But after the execution of i++ (in first line) it will get cache the value. Later on the value is updated and gets 24. According to the program, as the variable i is not volatile so the changes will be done in the local cache of ThreadA,
Now when ThreadB accesses the decrement() method the value of i is as updated by ThreadA i.e. 24. How could that be possible?
Assuming that threads won't see each updates that other threads make to shared data is as inappropriate as assuming that all threads will see each other's updates immediately.
The important thing is to take account of the possibility of not seeing updates - not to rely on it.
There's another issue besides not seeing the update from other threads, mind you - all of your operations act in a "read, modify, write" sense... if another thread modifies the value after you've read it, you'll basically ignore it.
So for example, suppose i is 5 when we reach this line:
i = i * 2;
... but half way through it, another thread modifies it to be 4.
That line can be thought of as:
int tmp = i;
tmp = tmp * 2;
i = tmp;
If the second thread changes i to 4 after the first line in the "expanded" version, then even if i is volatile the write of 4 will still be effectively lost - because by that point, tmp is 5, it will be doubled to 10, and then 10 will be written out.
As specified in JLS 8.3.1.4:
The Java programming language allows threads to access shared
variables (§17.1). As a rule, to ensure that shared variables are
consistently and reliably updated, a thread should ensure that it has
exclusive use of such variables by obtaining a lock that,
conventionally, enforces mutual exclusion for those shared variables........A field may be
declared volatile, in which case the Java Memory Model ensures that
all threads see a consistent value for the variable
Although not always but there is still a chance that the shared values among threads are not consistenly and reliably updated, which would lead to some unpredictable outcome of program. In code given below
class Test {
static int i = 0, j = 0;
static void one() { i++; j++; }
static void two() {
System.out.println("i=" + i + " j=" + j);
}
}
If, one thread repeatedly calls the method one (but no more than Integer.MAX_VALUE times in all), and another thread repeatedly calls the method two 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, the shared values of i and j might be updated out of order.
But if you declare i and j to be volatile , This allows method one and method two to be executed concurrently, but guarantees that accesses to the shared values for i and j occur exactly as many times, and in exactly the same order, as they appear to occur during execution of the program text by each thread. Therefore, the shared value for j is never greater than that for i,because each update to i must be reflected in the shared value for i before the update to j occurs.
Now i came to know that common objects (the objects that are being shared by multiple threads) are not cached by those threads. As the object is common, Java Memory Model is smart enough to identify that common objects when cached by threads could produce surprising results.
How could that be possible?
Because there is nowhere in the JLS that says values have to be cached within a thread.
This is what the spec does say:
If you have a non-volatile variable x, and it's updated by a thread T1, there is no guarantee that T2 can ever observe the change of x by T1. The only way to guarantee that T2 sees a change of T1 is with a happens-before relationship.
It just so happens that some implementations of Java cache non-volatile variables within a thread in certain cases. In other words, you can't rely on a non-volatile variable being cached.

Volatile and atomic operation in java

I have read article concerning atomic operation in Java but still have some doubts needing to be clarified:
int volatile num;
public void doSomething() {
num = 10; // write operation
System.out.println(num) // read
num = 20; // write
System.out.println(num); // read
}
So i have done w-r-w-r 4 operations on 1 method, are they atomic operations? What will happen if multiple threads invoke doSomething() method simultaneously ?
An operation is atomic if no thread will see an intermediary state, i.e. the operation will either have completed fully, or not at all.
Reading an int field is an atomic operation, i.e. all 32 bits are read at once. Writing an int field is also atomic, the field will either have been written fully, or not at all.
However, the method doSomething() is not atomic; a thread may yield the CPU to another thread while the method is being executing, and that thread may see that some, but not all, operations have been executed.
That is, if threads T1 and T2 both execute doSomething(), the following may happen:
T1: num = 10;
T2: num = 10;
T1: System.out.println(num); // prints 10
T1: num = 20;
T1: System.out.println(num); // prints 20
T2: System.out.println(num); // prints 20
T2: num = 20;
T2: System.out.println(num); // prints 20
If doSomething() were synchronized, its atomicity would be guaranteed, and the above scenario impossible.
volatile ensures that if you have a thread A and a thread B, that any change to that variable will be seen by both. So if it at some point thread A changes this value, thread B could in the future look at it.
Atomic operations ensure that the execution of the said operation happens "in one step." This is somewhat confusion because looking at the code 'x = 10;' may appear to be "one step", but actually requires several steps on the CPU. An atomic operation can be formed in a variety of ways, one of which is by locking using synchronized:
What the volatile keyword promises.
The lock of an object (or the Class in the case of static methods) is acquired, and no two objects can access it at the same time.
As you asked in a comment earlier, even if you had three separate atomic steps that thread A was executing at some point, there's a chance that thread B could begin executing in the middle of those three steps. To ensure the thread safety of the object, all three steps would have to be grouped together to act like a single step. This is part of the reason locks are used.
A very important thing to note is that if you want to ensure that your object can never be accessed by two threads at the same time, all of your methods must be synchronized. You could create a non-synchronized method on the object that would access the values stored in the object, but that would compromise the thread safety of the class.
You may be interested in the java.util.concurrent.atomic library. I'm also no expert on these matters, so I would suggest a book that was recommended to me: Java Concurrency in Practice
Each individual read and write to a volatile variable is atomic. This means that a thread won't see the value of num changing while it's reading it, but it can still change in between each statement. So a thread running doSomething while other threads are doing the same, will print a 10 or 20 followed by another 10 or 20. After all threads have finished calling doSomething, the value of num will be 20.
My answer modified according to Brian Roach's comment.
It's atomic because it is integer in this case.
Volatile can only ganrentee visibility among threads, but not atomic. volatile can make you see the change of the integer, but cannot ganrentee the integration in changes.
For example, long and double can cause unexpected intermediate state.
Atomic Operations and Synchronization:
Atomic executions are performed in a single unit of task without getting affected from other executions. Atomic operations are required in multi-threaded environment to avoid data irregularity.
If we are reading/writing an int value then it is an atomic operation. But generally if it is inside a method then if the method is not synchronized many threads can access it which can lead to inconsistent values. However, int++ is not an atomic operation. So by the time one threads read it’s value and increment it by one, other thread has read the older value leading to wrong result.
To solve data inconsistency, we will have to make sure that increment operation on count is atomic, we can do that using Synchronization but Java 5 java.util.concurrent.atomic provides wrapper classes for int and long that can be used to achieve this atomically without usage of Synchronization.
Using int might create data data inconsistencies as shown below:
public class AtomicClass {
public static void main(String[] args) throws InterruptedException {
ThreardProcesing pt = new ThreardProcesing();
Thread thread_1 = new Thread(pt, "thread_1");
thread_1.start();
Thread thread_2 = new Thread(pt, "thread_2");
thread_2.start();
thread_1.join();
thread_2.join();
System.out.println("Processing count=" + pt.getCount());
}
}
class ThreardProcesing implements Runnable {
private int count;
#Override
public void run() {
for (int i = 1; i < 5; i++) {
processSomething(i);
count++;
}
}
public int getCount() {
return this.count;
}
private void processSomething(int i) {
// processing some job
try {
Thread.sleep(i * 1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
OUTPUT: count value varies between 5,6,7,8
We can resolve this using java.util.concurrent.atomic that will always output count value as 8 because AtomicInteger method incrementAndGet() atomically increments the current value by one. shown below:
public class AtomicClass {
public static void main(String[] args) throws InterruptedException {
ThreardProcesing pt = new ThreardProcesing();
Thread thread_1 = new Thread(pt, "thread_1");
thread_1.start();
Thread thread_2 = new Thread(pt, "thread_2");
thread_2.start();
thread_1.join();
thread_2.join();
System.out.println("Processing count=" + pt.getCount());
}
}
class ThreardProcesing implements Runnable {
private AtomicInteger count = new AtomicInteger();
#Override
public void run() {
for (int i = 1; i < 5; i++) {
processSomething(i);
count.incrementAndGet();
}
}
public int getCount() {
return this.count.get();
}
private void processSomething(int i) {
// processing some job
try {
Thread.sleep(i * 1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
Source: Atomic Operations in java

Categories