Tuesday, March 25, 2008

Java : Threading Tricks

Stopping Thread : read the great story
Stopping a Thread is complicated. In the beginning the Thread.stop() method was added for this purpose, but is has been
deprecated for a long time. The reason is when some thread calls stop() on a victim thread, a ThreadDeath error is thrown inside the victim thread. And while this error propagates up the stacktrace, all locks the victim thread owns, are released. This means that the victim-thread could leave objects (on which it held locks) in an inconsistent state. So stopping a thread should be a cooperative mechanism between threads: the victim thread and the initiating thread both need to agree upon a protocol being used.

Luckily I don't see the usage of Thread.stop() (or even worse, the Thread.destroy()) often, but the idiom displayed in the example below, is something I do see regularly. Although the exception handling is sometimes forgotten. This Task is executed by some thread, and when a different thread wants to stop this Task, it calls the stop method on the Task and the stop variable is set to true. As soon as the victim thread starts the next iteration of the loop, it reads the stop variable, ends the loop and returns from the run method (returning from the run method eventually terminates the victim thread).
Concurrency handling with String:

** Problem :
public class Worker {
private final String lock = "A rusty old lock";

public void work() {
synchronized(lock) {
println lock;
// some work takes a long time
}
}
}
>> when the VM runs our application, our String is added to the String pool.
This means, that only one one instance of our lock is present in our VM, instead of a lock per instance.
So, is that instead of instance-based lock, we are locking a class level
and this can cause some unexpected deadlocks or slowdowns in the application.
Solution >>

public
class Worker {
private final Object lock = new Object() {
public String toString() {
return “c00l lock”;
}

public void work() {
synchronized(lock) {
// some work takes a long time
}
}
}
*** this is how we can have instance-based locking with a lock name

Nested Locking

Loop Invariant Code Discussion
Here goes the part of the discussion
"...
class Animator implements Runnable {
private volatile boolean stop = false;
public void stop() { stop = true; }
public void run() {
while (!stop) {
oneStep();
try { Thread.sleep(100); } …;
}
}
private void oneStep() { /*...*/ }
}

This is a pretty common idiom. One thread calls run(), and another thread (eventually) calls stop(), which sets the stop flag to true, and halts the loop. This is fairly intuitive.

What is not intuitive about this code is that if the variable is not declared volatile, then regardless of whether another thread calls stop(), this code is not guaranteed to terminate. A compiler (in this case, likely Java's JIT compiler) can:
  1. Look at the run() method,
  2. Notice that stop is never updated, and therefore
  3. Hoist the read of stop outside the loop.
The resulting code would look something like this:

public void run() {
if (!stop) {
while (true) {
oneStep();
try { Thread.sleep(100); } …;
}
}
}

... which would likely run forever. But only if stop is not declared volatile.

Now, the questioner asked if I knew of any compilers that were likely to do this. Pretty much every modern compiler does loop invariant code motion -- basically, if it decides that some program instruction will evaluate the same on every loop iteration (as the read of stop does), then it will arrange the code so that program instruction is only executed once, before the loop."

Here goes nice one - Atomicity, Ordering and Visibility

No comments: