Why use private locks in Java?
What is wrong with the following code?
public class Counter { public synchronized int getNext() { return ++value; } private int value; }
It is correctly synchronized, but can cause a liveness problem if some code obtains a lock on an instance of Counter:
public class Test { public static void main(String args[]) throws Exception { Counter c = new Counter(); CounterThread ct = new CounterThread(c); // This will cause c.next() to wait for the lock on c to be // released, which will never happen. // The program will hang here. synchronized (c) { ct.start(); ct.join(); } } public static class CounterThread extends Thread { public CounterThread(Counter counter) { this.counter = counter; } public void run() { System.out.println(counter.next()); } private Counter counter; } }
The solution is to use a private lock object rather than using Counter’s intrinsic lock. Make sure that this lock is not published:
public class Counter { public int next() { synchronized (lock) { return ++value; } } private int value; private Object lock = new Object(); }