public class VolatileOne {
private static boolean ready ;
private static int number ;
private static class ReaderThread extends Thread{
#Override
public void run() {
while (!ready){
Thread.yield();
}
System.out.print(number);
}
}
public static void main(String[] args) {
new ReaderThread().run();
ready = true;
number = 50;
}
}
After running this code, the program does not stop, which is obvious because the thread backs up variables ready into the memory of its own process. When I use volatile keyword to modify read
private volatile static boolean ready ;
the read variable will not be copied into process memory at this time. But the program can't stop. What's the reason? Is it related to the static keyword?
If you want the program to output 50 and return, what should you do?
You need call start to execute the code in another thread. Check this for the difference between run and start.
Call join to wait the ReaderThread finish.
volatile keyword can build a happens-before relationship between the write and the read thread, you can put number = 50; before ready = true;, which makes sure the reader will notice number is 50 when it notice ready is true.
Example:
Thread reader = new ReaderThread();
reader.start();
number = 50;
ready = true;
reader.join();
Related
I was given a question by my friend and was asked to explain why the program could get hung in infinite loop.
public class Test {
private static boolean flag;
private static int count;
private static class ReaderThread extends Thread {
public void run() {
while (!flag)
Thread.yield();
System.out.println(count);
}
}
public static void main(String[] args) {
new ReaderThread().start();
count = 1;
flag = true;
}
}
I was sure that it cannot happen. But it did actually happen one time (out of probably 50 times).
I am not able to explain this behavior. Is there any catch that I am missing?
From book - Java Concurrency In Practice (this example seems to be taken from the book itself).
When the reads and writes occur in different threads, there is no guarantee that the reading thread will see a value written by another thread on a timely basis, or even at all because threads might cache these values.
In order to ensure visibility of memory writes across threads, you must use synchronization or declare variable as volatile.
I am trying to figure what would be the best way to fix this broken concurrency issue with this kind of code. I have tried adding a lock around "index++" but is there a better way of achieving concurrency?
public class MainClass {
public static short index = 0;
public static void main(String[] args) {
MainClass testConc = new MainClass();
Thread thr1 = new Thread(testConc.new MyRunnable());
thr1.start();
Thread thr2 = new Thread(testConc.new MyRunnable());
thr2.start();
}
class MyRunnable implements Runnable {
private static final Object lock = new Object();
public void run() {
while (index < 99) {
System.out.println(index);
synchronized(lock) {
index++;
}
}
}
}
}
You should have the lock at the same level (MainClass) as the data it is used for protecting. Class variable index should actually have private scope, because synchronization only happens in-class.
Also, as pointed out by Tomáš in the comment, the variable should be marked as volatile, which guarantees that any changes to the its value are visible to all threads (since Java 5). This removes the need to synchronize read access to index. So the corrected code looks something like:
public class MainClass {
private static volatile short index = 0;
private static final Object lock = new Object();
...
If you want the program to output the indices from 0 to 98 in order and only once per index value, you need to modify the run() method into this:
public void run() {
while (index < 99) {
synchronized (lock) {
// double-check for threads that made it here
// before #index got incremented to 99 by the thread that
// made the final increment
if (index < 99) {
System.out.println(index);
index++;
}
}
}
}
Notice that a double-check for index < 99 is required because index may have been changed by an another thread after the value was evaluated in the while condition. You'll see this if you increase the number of threads that are spawned by MainClass using the old version of run().
AtomicInteger would be better than locking around index++
It is designed especially for that use case.
Also by locking you are not achieving concurrency but thread safety/atomicity (if implemented properly).
By the way, I don't see the 'broken concurrency issue' in your code.
As far as I know, volatile variables will be always read and written from the main memory. Then I think about the Singleton class. Here is how my program is:
1. Singleton class
public class Singleton {
private static Singleton sin;
private static volatile int count;
static{
sin = new Singleton();
count = 0;
}
private Singleton(){
}
public static Singleton getInstance(){
return sin;
}
public String test(){
count++;
return ("Counted increased!" + count);
}
}
2. Main class
public class Java {
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
Derived d1 = new Derived("d1");
d1.start();
Derived d2 = new Derived("d2");
d2.start();
Derived d3 = new Derived("d3");
d3.start();
}
;
}
class Derived extends Thread {
String name;
public Derived(String name){
this.name = name;
}
public void run() {
Singleton a = Singleton.getInstance();
for (int i = 0; i < 10; i++) {
System.out.println("Current thread: "+ name + a.test());
}
}
}
I know this maybe a dumb question, but i'm not good at multithreading in Java thus this problem confuses me a lot. I thought the static volatile int count variable in Singleton class will always have the latest value, but apparently it does not...
Can someone help me to understand this?
Thank you very much.
The problem is that volatile has nothing to do with thread synchronization. Even though the read from static volatile int count would indeed always return the latest value, multiple threads may write the same new value back into it.
Consider this scenario with two threads:
count is initialized zero
Thread A reads count, sees zero
Thread B reads count, sees zero
Thread A advances count to 1, stores 1
Thread B advances count to 1, stores 1
Thread A writes "Counted increased! 1"
Thread B writes "Counted increased! 1"
Both threads read the latest value, but since ++ is not an atomic operation, once the read is complete, each thread is on its own. Both threads independently compute the next value, and then store it back into the count variable. The net effect is that a variable is incremented once, even though both threads performed the increment.
If you would like to increment an int from multiple threads, use AtomicInteger.
As Jon Skeet indicated, it would be best if you use AtomicInteger. Using volatile variables reduces the risk of memory consistency errors, but it doesn't eliminate the need to synchronize atomic action.
I think this modification would help with your problem.
public synchronized String test(){
count++;
return ("Counted increased!" + count);
}
Reader threads are not doing any locking and until writer thread comes out of synchronized block, memory will not be synchronized and value of 'sin' will not be updated in main memory. both threads reads the same values and thus updates it by adding one, if you want to resolve make test method synchronised.
Read more: http://javarevisited.blogspot.com/2011/06/volatile-keyword-java-example-tutorial.html#ixzz3PGYRMtgE
Does volatile write assure that whatever writes (non-volatile / volatile writes) happens before it in one thread will be visible to other thread?
Will the following given code always produce 90,80 as output?
public class MyClass
{
private boolean flag = false;
private volatile int volatileInt = 0;
private int nonVolatileInt = 0;
public void initVariables()
{
nonVolatileInt = 90; // non-volatile write
volatileInt = 80; // volatile write
flag = true; // non-volatile write
}
public void readVariables()
{
while (flag == false)
{}
System.out.println(nonVolatileInt + ","+ volatileInt);
}
public static void main(String st[])
{
final MyClass myClass = new MyClass();
Thread writer = new Thread( new Runnable()
{
public void run()
{
myClass.initVariables();
}
});
Thread reader = new Thread ( new Runnable()
{
public void run()
{
myClass.readVariables();
}
});
reader.start();writer.start();
}
}
My concern is the method initVariables(). Isn't JVM has a freedom to reorder the code blocks in following way?:
flag = true;
nonVolatileInt = 90 ;
volatileInt = 80;
And consequently, we get the output by the reader thread as : 0,0
Or, they can be reordered in the following way:
nonVolatieInt = 90;
flag = true;
volatileInt = 80;
And consequently, we get the output by the reader thread as : 90,0
A volatile write ensures that writes already performed do not appear after this write. However to ensure you see this you need to perform a volatile read first.
And consequently, we get the output by the reader thread as : 90,0
Correct. However if you perform your reads correctly you cannot get 0, 80
0, 0 - ok
90, 0 - ok
90, 80 - ok
0, 80 - breaks happens before.
However, your reads do not ensure happens before behaviour as it doesn't perform the volatile read first.
System.out.println(nonVolatileInt + ","+ volatileInt);
This reads the non-volatile fields first, so you could see an old version of the non-volatile field and a new version of the volatile field.
Note: in reality, you are highly unlikely to see a problem. This is because caches invalidate a whole cache line at a time and if these fields are in the same 64-byte block, you shouldn't see an inconsistency.
What is more likely to be a problem is this loop.
while (flag == false)
{}
The problem is; the JIT can see your thread nevers writes to flag so it can inline the value. i.e. it never needs to read the value. This can result in an infinite loop.
http://vanillajava.blogspot.co.uk/2012/01/demonstrating-when-volatile-is-required.html
Here I have three simple classes:
Class 1:
public class ThreadSyncMain {
public static int count = 0; // volatile is not use
public static void main(String[] args) {
Thread thread1 = new Thread( new Thread1(),"Thread1" );
Thread thread2 = new Thread( new Thread2(),"Thread2");
thread1.start();
thread2.start();
}
}
Class 2:
public class Thread1 implements Runnable{
public void run() {
System.out.println("Thread1 Count :: "+ThreadSyncMain.count);
ThreadSyncMain.count++;
}
}
Class 3:
public class Thread2 implements Runnable{
public void run() {
System.out.println("Thread2 Count :: "+ThreadSyncMain.count);
}
}
The output is:
Thread1 Count :: 0
Thread2 Count :: 1
This means thread1 changed the value of count. So why change in thread1 affects in thread2 as I am not using any "volatile" keyword. Is "volatile" keyword not a matter in this scenario? How can I modify the code so as to test "volatile"?
Thanks in advance.
Update part:
I am updating the code after doing some hit and trial testing. Class 1 remains same. Here is the updated code:
Class 2: I added 100 millisecond delay.
public class Thread1 implements Runnable{
public void run() {
System.out.println("Thread1 Count :: "+ThreadSyncMain.count);
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
ThreadSyncMain.count++;
}
}
Class 3: Added while loop. Inside it count is continuously monitored.
public class Thread2 implements Runnable{
public void run() {
while(true)
{
if(ThreadSyncMain.count == 1)
{
System.out.println("Thread2 Count :: "+ThreadSyncMain.count);
}
}
}
}
Now in this situation I have got the following outputs:
1. If "volatile" is not used in class1 output is:
Thread1 Count :: 0
2. If "volatile" is used in class1 output is:
Thread1 Count :: 0
Thread2 Count :: 1
Thread2 Count :: 1
Thread2 Count :: 1
.
.
.
Why volatile comes into picture in this scenario?
There's a memory view associated with each thread. These views are not guaranteed to be consistent between threads without the usage of locks. As such, sharing a variable as you've done above (without volatile) will work, since it's visible across threads, but can give you unreliable results. Using the volatile keyword means that the variable is consistently read between threads.
See here, and in particular note:
Volatile fields are special fields which are used for communicating
state between threads. Each read of a volatile will see the last write
to that volatile by any thread; in effect, they are designated by the
programmer as fields for which it is never acceptable to see a "stale"
value as a result of caching or reordering.
Volatile will guarantee the side effects from thread 1 become visible to thread 2. Without volatile, changes might, or might not, be visible.
Testing the effect of volatile is difficult, since it depends on low level aspects like hardware architecture, threading implementation, compiler optimization, and exact timing of even by the scheduler.
If I were to do so, I would write multithreaded tests that generate a high concurrency, and make sure I run on a multi-processor implementation. Then I might observe differences between code with and without volatile. The outcome of the tests would still be undeterministic.
It is possible the compiler isn't caching counter because it is a class wide variable. So the writes are in memory.
If you want to test volatile and non volatile write/reads..
public class VolatileExperiment
{
private int counter ;
private volatile int volatile_counter;
public void Counter()
{
new Thread( new Runnable(){
public void run()
{
++counter;
++volatile_counter;
//print
}
}).start();
new Thread( new Runnable(){
public void run()
{
++counter;
++volatile_counter;
//print
}
}).start();
//print counter
//print volatile
}
}
Using volatile ensures that compiler doesn't optimize code, so writes are done in memory and not in thread memory. So you should see volatile_counter updated.. while counter may not be affected