How to demonstrate java multithreading visibility problems?
How to demonstrate java multithreading visibility problems?
If variables in Java are accessed from multiple threads, one must ensure that they are safely published. This usually means using synchronizedor volatile.
I have got the impression, that some of my colleagues do not take this issue seriously, since they "never heard of volatile before and their programs have worked for years".
So my question is:
Can someone provide an example Java program/snippet, that reliably shows data visibility problems.
I think running a program and seeing the unexpected NPE or stale variable value would help more, than just theoretic explanations, that cannot be demonstrated.
Thanks a lot for your help!
Update: Just to emphasis the point again. I have read Java Concurreny in Practice and know examples that theoretically have visibility issues. What I am looking for is a way to actually demonstrate them. I am not sure, that this is actually possible, but maybe there is a jvm configuration or something similar that allows it.
Answer by Jesper for How to demonstrate java multithreading visibility problems?
Make them read the book Java Concurrency in Practice by Java concurrency guru Brian Goetz. That book is a must-read for anybody who has to write any serious concurrent software in Java!
Ofcourse saying "I've never heard of volatile and my programs have worked for years" is a dumb argument from ignorance.
Answer by aioobe for How to demonstrate java multithreading visibility problems?
The most common example brought up to emphasis the importance of using volatile is the while(keepRunning) example:
public class Test extends Thread { boolean keepRunning = true; public static void main(String[] args) throws InterruptedException { Test t = new Test(); t.start(); Thread.sleep(1000); t.keepRunning = false; System.out.println(System.currentTimeMillis() + ": keepRunning is false"); } public void run() { while (keepRunning) System.out.println(System.currentTimeMillis() + ": " + keepRunning); } } Since keepRunning may (validly) be kept in cache of the thread running the while-loop, this program may print "true" for keepRunning long after keepRunning is set to false.
Note however, that there is no reliable way of exposing race-conditions. (See my other answer.) This example may expose it under certain circumstances on certain combinations of hardware / operating system / jvm.
Answer by aioobe for How to demonstrate java multithreading visibility problems?
Can someone provide an example Java program/snippet, that reliably shows data visibility problems.
No, there is no reliably example that shows data visibility problems.
The reason is that any valid execution of a program with volatile is also a valid execution of the same program without volatile. (The opposite is obviously not true though!)
Answer by David Rodrguez - dribeas for How to demonstrate java multithreading visibility problems?
By modifying the example here by removing operations I have come up with an example that consistently fails in my environment (the thread never stops running).
// Java environment: // java version "1.6.0_0" // OpenJDK Runtime Environment (IcedTea6 1.6.1) (6b16-1.6.1-3ubuntu3) // OpenJDK 64-Bit Server VM (build 14.0-b16, mixed mode) public class Test2 extends Thread { boolean keepRunning = true; public static void main(String[] args) throws InterruptedException { Test2 t = new Test2(); t.start(); Thread.sleep(1000); t.keepRunning = false; System.out.println(System.currentTimeMillis() + ": keepRunning is false"); } public void run() { while (keepRunning) {} } } Note that this type of problems are quite dependent on the compiler/runtime/system. In particular the compiler can determine to add instructions to read the variable from memory even if it is not volatile --so the code would work--, the vm and jit can optimize away the reads from memory and use only registers, and even the processor can reorder instructions --that would not affect this case, but in other multithreaded cases it can affect the perceived state from other threads if more than one variable are modified.
Answer by soil7c3 for How to demonstrate java multithreading visibility problems?
I have a snippet of code for you:
package test; public class LoopTest { private boolean done = false; /** * @param args */ public void start() { System.out.println(System.getProperty("java.vm.name")); System.out.println(System.getProperty("java.version")); for (int i = 0; i < 100; i++) { startNewThread(); } try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } done = true; System.out.println("forcing end"); } private void startNewThread() { new Thread(new Runnable() { public void run() { long i = 0; while(!done) { i++; if(i % 100L == 0) { System.out.println("still working " + i); } } System.out.println("ending " + i); } }).start(); } public static void main(String[] args) { new LoopTest().start(); } } This example run in JVM Server mode generated this output on my machine:
.. .. ending 14100 still working 14800 ending 14800 still working 26500 ending 26500 still working 18200 ending 18200 still working 9400 ending 9400 still working 1300 ending 1300 still working 59500 ending 59500 still working 1700 still working 75400 ending 75400 still working 33500 ending 33500 still working 36100 ending 36100 still working 121000 ending 121000 still working 3000 ending 3000 ending 1700 still working 5900 ending 5900 still working 7800 ending 7800 still working 7800 ending 7800 still working 6800 ending 6800 still working 5300 ending 5300 still working 9100 still working 10600 ending 10600 still working 9600 ending 9600 still working 10000 ending 10000 ending 9100 still working 1700 ending 1700 .. .. Look at the "ending #" statements: all of them have a number which is a multiple of 100 which is quite unlikely to happen, i think. My interpretation is that there is an visibility issue which causes the threads to still read done == false although it already has been updated to true. After the call to the synchronized System.out.println() method with the "still working #" statement, the threads read the updated value for done and exit.
Or does anyone see a mistake in my code / interpretation?
Answer by Narendra Pathai for How to demonstrate java multithreading visibility problems?
public class NoVisibility { private static boolean ready = false; private static int number; private static class ReaderThread extends Thread { @Override public void run() { while (!ready) { Thread.yield(); } System.out.println(number); } } public static void main(String[] args) throws InterruptedException { new ReaderThread().start(); number = 42; Thread.sleep(20000); ready = true; } } Place the Thread.sleep() call for 20 secs what will happen is JIT will kick in during those 20 secs and it will optimize the check and cache the value or remove the condition altogether. And so the code will fail on visibility.
To stop that from happening you MUST use volatile.
Answer by Biman Tripathy for How to demonstrate java multithreading visibility problems?
An extension to @David's code (configuration Java6 64bit, Eclipse Juno SR2):
public class NoVisibility_Demonstration extends Thread { boolean keepRunning = true; public static void main(String[] args) throws InterruptedException { NoVisibility_Demonstration t = new NoVisibility_Demonstration(); t.start(); Thread.sleep(1000); t.keepRunning = false; System.out.println(System.currentTimeMillis() + ": keepRunning is false"); } public void run() { int x = 10; while (keepRunning) { //System.out.println("If you uncomment this line, the code will work without the visibility issue"); x++; } System.out.println("x:"+x); } } Using this example, you can show both scenarios. When you uncomment the line in the while loop in run(), the visibility issue is resolved. The reason is that println() statements use synchronization. Detailed discussion HERE
Fatal error: Call to a member function getElementsByTagName() on a non-object in D:\XAMPP INSTALLASTION\xampp\htdocs\endunpratama9i\www-stackoverflow-info-proses.php on line 72

0 comments:
Post a Comment