Возникает мертвая блокировка, тогда поток ожидает условия, которое никогда не произойдет.
Очевидный случай, когда вы пытаетесь заблокировать две блокировки, заблокированные в разном порядке разными потоками.
ReentrantLock lock1 = new ReentrantLock();
ReentrantLock lock2 = new ReentrantLock();
public void methodA() {
lock1.lock();
lock2.lock();
// do something and un lock both.
}
public void methodB() {
lock2.lock();
lock1.lock();
// do something and un lock both.
}
Как видите, поток может вызвать метод A и получить lock1, ожидающий lock2, а другой поток вызвать метод B и получить lock2, ожидающий lock1.
Однако поток может заблокировать себя. Примером является ReentrantReadWriteLock, поскольку он не поддерживает обновление блокировки чтения до блокировки записи.
ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
rwl.readLock().lock();
// do we need to update?
rwl.writeLock().lock(); // will wait for the readLock() to be released!
Неясная возможность заблокировать себя - это использование подразумеваемых замков. Статический блок инициализатора неявно ориентирован на многопотоковое исполнение, поэтому используется блокировка, даже если статические блоки инициализатора не synchronized
class A {
private static int VALUE;
static {
Thread t = new Thread() {
public void run() {
// waits for the A class to load.
VALUE = someLongTask();
}
};
t.start();
// waits for the thread.
t.join();
}
}
Опять у вас тупик!