How to test liveness failures? - java

In Joshua Bloch's Effective Java, Item 66, he exemplifies a lifeness failure by failing to communicate a variable between threads.
// Broken! - How long would you expect this program to run?
public class StopThread {
private static boolean stopRequested;
public static void main(String[] args) throws InterruptedException {
Thread backgroundThread = new Thread(new Runnable() {
public void run() {
int i = 0;
while (!stopRequested)
i++;
}
});
backgroundThread.start();
TimeUnit.SECONDS.sleep(1);
stopRequested = true;
}
}
He says on his own machine this never terminates, and gives two reasons. I tried this on my own machine, on Oracle JDK 7u75 (newest 7), and it ALWAYS terminates after one second. I also tried starting the runtime with -XX:+AggressiveOpts without success. Is there any reason why this is not working as intended (edit: i.e. not looping forever)? Is Joshua using another runtime? I have a quad-core ivy bridge.

stopRequested is not volatile. So, there is no guarantee that the changes made to it by the main thread will be seen by the backgroundThread. Changes could be seen, changes might not be seen. There is no guarantee. So (as always), Joshua is right :)

Related

Do Android ART and HotSpot behave differently in non-volatile variable visibility?

I tested the below piece of code on HotSpot and Android ART, but with different results.
On HotSpot, MyThread never gets the updated isRunning, it get isRunning = true always...
But when I test it on ART, MyThread can get the updated isRunning and exit loop normally...
As I know about java happens-before rule, an non-volatile is not visible across multi-thread, just like the behave of the code below on Hotspot.
Does it depends on VM implementation? Or maybe Android ART has their own optimization?
class MyThread extends Thread {
public boolean isRunning = true;
#Override
public void run() {
System.out.println("MyThread running");
while (true) {
if (isRunning == false) break;
}
System.out.println("MyThread exit");
}
}
public class RunThread{
public static void main(String[] args) {
new RunThread().runMain();
}
public void runMain() {
MyThread thread = new MyThread();
try {
thread.start();
Thread.sleep(500);
thread.isRunning = false;
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
an non-volatile is not visible across multi-thread, just like the behave of the code below on Hotspot.
That's not quite right. A non-volatile write, absent any additional synchronization or other happens-before relationship, is not guaranteed to be visible to a read of that same variable in another thread. It's allowed to be visible, though. I've absolutely seen HotSpot make writes visible across threads despite no happens-before relationship. Based on my experience with this, I suspect that if you remove that Thread.sleep call in your code, HotSpot will also make the write to isRunning visible to the thread, despite the lack of any happens-before relationship between the write and the read.
You're definitely right that it's VM-specific, and it's possibly/likely even processor architecture–specific, since different architectures may give different amounts of synchronization for "free", or have different amounts of cache that affect whether a memory address is read from a core's cache or fetched from main memory.
In summary, you should never rely on this sort of behavior working any specific way on any specific VM—it's liable to change without warning.

Can this code result in a deadlock?

I am not very good at multithreading and am baffled by this code:
public class Main {
public static void main(String... args) throws Exception {
new Thread(Main::test).start();
}
private static synchronized void test() {
new Thread(Main::test).start();
System.out.println("TEST");
}
}
Can it result in a deadlock or not? If so, then why have I not been able to get it to deadlock? My thinking is, thread 1 acquires lock on test(), then another thread, created in test() tries to acquire it and they should be waiting on each other. But they aren't, why not?
I know, that adding join() in test() will make it result in a deadlock, but how come the example below doesn't use joins and deadlocks?
This code results in a deadlock literally every time I run it:
public class Main {
public static void main(String... args) {
new Thread(Main::test).start();
new Thread(Main::test2).start();
}
private static void test() {
synchronized (Integer.class) {
try {
Thread.sleep(1);
} catch (Exception e) {
}
synchronized (Float.class) {
System.out.println("Acquired float");
}
}
}
private static void test2() {
synchronized (Float.class) {
try {
Thread.sleep(1);
} catch (Exception e) {
}
synchronized (Integer.class) {
System.out.println("Acquired integer");
}
}
}
}
No, the code in the first example cannot deadlock. The newly started threads will simply wait until the previous thread exits the method to acquire the lock.
The code in the second example deadlocks because the locks are acquired in opposite order and because of the sleeps are reliably going to block each other.
When you're at the phase where you're first learning how to think about concurrency and related problems, I would very much recommend using physical props to keep your thoughts and hypotheses clear and explicit.
For example, grab a A3 sheet of paper, set up a "race track" where you use something like Monopoly pieces to signify what you're doing in your code, what you expect to happen, and what your experiments show actually happens.
When your experiments don't work out, take a small piece of the beginning first, and verify it. Then add some more, and so on.
It helps if you read about how actual computers (not the CS ideal or conceptual computers) currently work. How the CPU gets data out of the main memory into its cache. How two or three CPUs decide which one of them can handle data in one cache line at a time. Then, how the Java Memory Model needs you to write your source code so that the JVM knows what you actually mean to happen.

Different outcome of java multi-thread due to length of sleep()?

This code end up with different results if I change the parameter of sleep(), and here is some sample outcomes:
1.sleep(1l), the thread will always terminate automaticlly, the "Stoped" statement will always be printed, and the icon of "Terminate" in Eclipse will be grey too. (seems working perfectly huh?)
2.sleep(1000l), here comes the problem, if main thread sleeps for 1 second, the Thread v will never terminated automaticlly, the "Stoped" will not be printed, and the icon of "Terminate" is red, which means there is still some thread running.
I know it could be solved if I add "volitale" for the parameter "isRunning", but I wonder why and how does the sleep() statement affect the outcome?
PS:I'm a newbie for both java and english, so I apologize for any possible discomforts due to this question.
public class VolitaleTest {
public static void main(String[] args) throws InterruptedException {
Vo v = new Vo();
new Thread(v).start();
Thread.sleep(1000l);
v.setRunning(false);
System.out.println(v.i);
}
}
class Vo implements Runnable {
private boolean isRunning = true;
int i = 0;
public void run() {
while (isRunning) {
i++;
// System.out.println("Running");
/*
* Once you add this statement, you will always be able to terminate
* the program automatically, no matter how long the thread sleeps.
*/
}
System.out.println("Stoped.");
}
public void setRunning(boolean isRunning) {
this.isRunning = isRunning;
}
}
volatile makes it possible for what one thread wrote up to and including writing to the volatile variable to be visible to another thread starting from when it reads that variable. If the variable is not volatile then that happens-before memory relationship is not guaranteed.

Why do thread behave different with different run method body?

This code is from Effective Java (Item 66): (without sync or volatile this never ends)
public class ThreadPractice {
static boolean canrunstatic;
public static void main(String[] args) throws InterruptedException {
Thread backgroundThread = new Thread(new Runnable() {
public void run() {
int i = 0;
while (!canrunstatic){i++;}
System.out.println("finished");
}
});
backgroundThread.start();
TimeUnit.SECONDS.sleep(1);
canrunstatic = true;
}
As Bloch mentioned in that chapter it will never write "finished" to the console. I've been playing around with this class, and add that line to the runnable run method:
System.out.println("im still running");
With this the while loop doesn't only increment i but prints out this string in every loop. But what drives me crazy, that this way the thread stops after 1 sec, when main thread comes back from sleep.
modified: (stops without volatile/sync)
public class ThreadPractice {
static boolean canrunstatic;
public static void main(String[] args) throws InterruptedException {
Thread backgroundThread = new Thread(new Runnable() {
public void run() {
int i = 0;
while (!canrunstatic){i++;System.out.println("im still running");}
System.out.println("finished");
}
});
backgroundThread.start();
TimeUnit.SECONDS.sleep(1);
canrunstatic = true;
}
So what is the logic behind this?
Precisely, it is just not guaranteed that the thread will ever stop, but it is not forbidden that it does stop. The logic behind this is provided by the Java Memory Model, which is a rather complicated topic, but needed in order to understand Multithreading in Java.
The concept is that a write to a non-volatile field of one thread is only required to be seen by another thread if these two actions synchronize with each other. A compiler is allow to reorder some actions if the behavior exhibited by the thread it is executed in does not change. But another thread might see this. So you need proper synchronization in order to tell the compiler that reordering is not allowed in some parts.
Read the full paper about this here: JSR-133
Writing data to the console is often implemented a thread safe operation.
In that case your act of writing data to the console can also trigger updating of the canrunstatic variable as seen by your backgroundThread.
Note that this is not promised by the Java Memory Model, nor by the implementation of java System.out

I am confused, is volatile really useful?

I wrote an example trying to understand volatile.
public class VolatileExample {
private volatile boolean close = false;
public void shutdown() {
close = true;
}
public void work(){
Thread t1 = new Thread(new Runnable(){
public void run(){
while (!close) {
}
}
});
Thread t2 = new Thread(new Runnable(){
public void run(){
while (!close) {
shutdown();
}
}
});
t1.start();
t2.start();
try {
t1.join();
t2.join();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static void main(String[] args){
VolatileExample volatileExample = new VolatileExample();
volatileExample.work();
}
}
it did stop as I expected. However, when I took the volatile away from the close tag, I have tried a lot of times---I expect the program will not stop because the thread t1 cannot see the change made by thread t2 on the close variable, but the programs ended successfully everytime. So I am confused, now that we can do it without volatile, what is volatile used for? Or can you give a better example that can make a difference between using volatile and not using volatile?
Thank you!
The memory model says only that changes to non- volatile fields may not be visible in other threads.
Perhaps your runtime environment was in a cooperative mood.
Changes to nonvolatile fields are sometimes visible to other threads, and sometimes not. How long they take to be visible to other threads can vary by orders of magnitude depending on what other processing the machine is doing, the number of processor chips and cores on the machine, the architecture of the cache memory on the machine, etc.
Ultimately, though, it comes down to this: buggy concurrency code can succeed the first 999,999 times, and fail on the millionth time. That often means it passes all tests, then fails in production when things really matter. For that reason, it's important when writing concurrent code that one make the best possible effort to ensure the code is correct - and that means using volatile for variables accessed from multiple threads even when it doesn't seem to make a difference in testing.

Categories