Changing mutex object reference
Writing concurrent execution modules is always tedious job. As most of the thread packages offer concurrency through locks, we should be careful about dealing with them. There is one side effect that compiler will not notice while we do this kind of programming. That is changing the reference of the mutex/lock on which we define our concurrency. Changing the reference of the mutex after acquiring the lock will have adverse effects.
Take a look at the following simple code fragment.
01
02 public class Reference {
03 static Object lock1 = new Object();
04 static Object lock2 = new Object();
05
06 public static void main(String[] args){
07 NopThread object = new NopThread();
08 Thread t1 = new Thread(object);
09 Thread t2 = new Thread(object);
10 t1.setName(“t1”);
11 t2.setName(“t2”);
12 t1.start();
13 t2.start();
14 }
15
16 }
17
18 class NopThread implements Runnable{
19 String shared = null;
20 public void run(){
21 synchronized (Reference.lock1) {
22 System.out.println(Thread.currentThread().getName() + “ has accuired the lock”);
23 shared = Thread.currentThread().getName();
24 Reference.lock1 = Reference.lock2;
25 try{
26 Thread.sleep(1000);
27 }catch(Exception e){
28 e.printStackTrace();
29 }
30 System.out.println(“Exiting thread: “ + shared);
31 }
32 }
33 }
Output:
t1 has accuired the lock
t2 has accuired the lock
Exiting thread: t2
Exiting thread: t2
Here NopThread is a runnable by a thread. It just uses a shared variable (shared) that gets updated by the run method with the name of the current thread. And that shared variable is controlled by lock1. If, for some reason lock1’s reference is changed in the middle of execution, worst can happen. Since the next thread that tries to acquire the lock for ‘lock1’ will actually acquires another object’s lock.
This type of problem can be detected during runtime if we design the communication with wait-notify methods. Since wait will throw a runtime error if we call wait() on the object whose lock is not acquired by current thread. However, busy/daemon threads who do not wait for other threads may not be connected with wait-notify constructs.
A warning by the compiler could avoid such errors to some extent (in straight forward cases). But it won’t be an easy task for compiler (even for developer) to detect such cases.