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();
}