Я думаю, что это довольно запутанный пример тупика - это добавляет другой шум в проблему.
Очень простой пример может быть достигнут путем использования Lock
объектов следующим образом:
public class App {
private static final Lock LOCKA = new ReentrantLock();
private static final Lock LOCKB = new ReentrantLock();
private static final class Locker1 implements Runnable {
@Override
public void run() {
while (true) {
try {
LOCKA.lockInterruptibly();
Thread.sleep(100);
LOCKB.lockInterruptibly();
System.out.println("Locker 1 Got locks");
} catch (InterruptedException ex) {
return;
}
LOCKB.unlock();
LOCKA.unlock();
}
}
}
private static final class Locker2 implements Runnable {
@Override
public void run() {
while (true) {
try {
LOCKB.lockInterruptibly();
Thread.sleep(100);
LOCKA.lockInterruptibly();
System.out.println("Locker 2 Got locks");
} catch (InterruptedException ex) {
return;
} finally {
LOCKA.unlock();
LOCKB.unlock();
}
}
}
}
public static void main(String[] args) throws IOException {
final ExecutorService executorService = Executors.newFixedThreadPool(2);
executorService.submit(new Locker1());
executorService.submit(new Locker2());
}
}
Приложение запускает два потока в исполнителю, мы затем эти потока вызывают два runnables.
Эти стопки пытаются приобрести блокировки на двух объектах Lock
в обратном порядке.
So Locker1
замки LOCKA
затем ждет несколько миллисекунд. Locker2
замки LOCKB
и ждет несколько миллисекунд, они пытаются и приобретают другой замок.
Ситуация такова, что Locker1
ждет LOCKB
и Locker2
ждет LOCKA
навсегда, как другой поток никогда не освобождает его.
Вы можете увидеть это довольно ясно в отвал нити для этих потоков:
"pool-1-thread-1" - Thread [email protected]
java.lang.Thread.State: WAITING
at sun.misc.Unsafe.park(Native Method)
- waiting to lock <7725204d> (a java.util.concurrent.locks.ReentrantLock$NonfairSync) owned by "pool-1-thread-2" [email protected]
at java.util.concurrent.locks.LockSupport.park(LockSupport.java:186)
at java.util.concurrent.locks.AbstractQueuedSynchronizer.parkAndCheckInterrupt(AbstractQueuedSynchronizer.java:834)
at java.util.concurrent.locks.AbstractQueuedSynchronizer.doAcquireInterruptibly(AbstractQueuedSynchronizer.java:894)
at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireInterruptibly(AbstractQueuedSynchronizer.java:1221)
at java.util.concurrent.locks.ReentrantLock.lockInterruptibly(ReentrantLock.java:340)
at com.boris.testbench.App$Locker1.run(App.java:32)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:334)
at java.util.concurrent.FutureTask.run(FutureTask.java:166)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:722)
Locked ownable synchronizers:
- locked <7567e1fa> (a java.util.concurrent.locks.ReentrantLock$NonfairSync)
- locked <5ad52411> (a java.util.concurrent.ThreadPoolExecutor$Worker)
"pool-1-thread-2" - Thread [email protected]
java.lang.Thread.State: WAITING
at sun.misc.Unsafe.park(Native Method)
- waiting to lock <7567e1fa> (a java.util.concurrent.locks.ReentrantLock$NonfairSync) owned by "pool-1-thread-1" [email protected]
at java.util.concurrent.locks.LockSupport.park(LockSupport.java:186)
at java.util.concurrent.locks.AbstractQueuedSynchronizer.parkAndCheckInterrupt(AbstractQueuedSynchronizer.java:834)
at java.util.concurrent.locks.AbstractQueuedSynchronizer.doAcquireInterruptibly(AbstractQueuedSynchronizer.java:894)
at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireInterruptibly(AbstractQueuedSynchronizer.java:1221)
at java.util.concurrent.locks.ReentrantLock.lockInterruptibly(ReentrantLock.java:340)
at com.boris.testbench.App$Locker2.run(App.java:51)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:334)
at java.util.concurrent.FutureTask.run(FutureTask.java:166)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:722)
Locked ownable synchronizers:
- locked <7725204d> (a java.util.concurrent.locks.ReentrantLock$NonfairSync)
- locked <6856c528> (a java.util.concurrent.ThreadPoolExecutor$Worker)
Мы можем видеть, что pool-1-thread-1
хочет замок на замок, принадлежащей pool-1-thread-2
и pool-1-thread-2
хочет замок на замок принадлежит pool-1-thread-1
,
Эта ситуация будет продолжаться навсегда, а значит, и в тупике.
Вы получаете тот же результат, но вместо использования двух потоков, порожденных вручную, он использует основной поток приложения (порожденный JVM) и один поток, порожденный вручную.
Он также использует synchronized
методы в двух Object
с, а не два Lock
объектов.
Что вы имеете в виду, как это currentThread работа? Он возвращает текущий поток. Создается поток, первый поток все еще существует. –
'' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' 'и ' 'currentThread' возвращает поток, из которого был вызван метод; как это работает? Взгляните на исходный код. –
Где создается нить A? Я новичок в java. @Dave Newton – srk