- Последовательный тупик: чрезмерная блокировка, в результате чего друг у друга удерживает блокировку, которую ожидает другая сторона, из-за порядка выполнения
- Взаимная блокировка ресурсов: несколько потоков ожидают одного и того же ресурса.
Тупик из-за заказа вызова
public class Test {
Object leftLock = new Object();
Object rightLock = new Object();
public static void main(String[] args) {
final Test test = new Test();
Thread a = new Thread(new Runnable() {
@Override public void run() {
int i=0;
while (i<10)
{
test.leftRight();
i++;
}
}
},"aThread");
Thread b = new Thread(new Runnable() {
@Override public void run() {
int i=0;
while (i<10)
{
test.rightleft();
i++;
}
}
},"bThread");
a.start();
b.start();
}
public void leftRight(){
synchronized (leftLock){
System.out.println(Thread.currentThread().getName()+":leftRight:get left");
synchronized (rightLock){
System.out.println(Thread.currentThread().getName()+":leftRight:get right");
}
}
}
public void rightleft(){
synchronized (rightLock){
System.out.println(Thread.currentThread().getName()+":rightleft: get right");
synchronized (leftLock){
System.out.println(Thread.currentThread().getName()+":rightleft: get left");
}
}
}
}
Вывод после запуска следующий
aThread:leftRight:get left
bThread:rightleft: get right
Вы можете найти следы взаимоблокировки через jstack
"bThread" prio=5 tid=0x00007fabb2001000 nid=0x5503 waiting for monitor entry [0x000000011d54b000]
java.lang.Thread.State: BLOCKED (on object monitor)
at main.lockTest.Test.rightleft(Test.java:52)
- waiting to lock <0x00000007aaee5748> (a java.lang.Object)
- locked <0x00000007aaee5758> (a java.lang.Object)
at main.lockTest.Test$2.run(Test.java:30)
at java.lang.Thread.run(Thread.java:745)
Locked ownable synchronizers:
- None
"aThread" prio=5 tid=0x00007fabb2801000 nid=0x5303 waiting for monitor entry [0x000000011d448000]
java.lang.Thread.State: BLOCKED (on object monitor)
at main.lockTest.Test.leftRight(Test.java:43)
- waiting to lock <0x00000007aaee5758> (a java.lang.Object)
- locked <0x00000007aaee5748> (a java.lang.Object)
at main.lockTest.Test$1.run(Test.java:19)
at java.lang.Thread.run(Thread.java:745)
Locked ownable synchronizers:
- None
можно увидетьbThread
держать замок0x00000007aaee5758
, пока жду0x00000007aaee5748
, но простоaThread
держать замок0x00000007aaee5748
и ждать0x00000007aaee5758
, что приводит к тупику
тупик голодания потока
public class ExecutorLock {
private static ExecutorService single=Executors.newSingleThreadExecutor();
public static class AnotherCallable implements Callable<String>{
@Override public String call() throws Exception {
System.out.println("in AnotherCallable");
return "annother success";
}
}
public static class MyCallable implements Callable<String>{
@Override public String call() throws Exception {
System.out.println("in MyCallable");
Future<String> submit = single.submit(new AnotherCallable());
return "success:"+submit.get();
}
}
public static void main(String[] args) throws ExecutionException, InterruptedException {
MyCallable task = new MyCallable();
Future<String> submit = single.submit(task);
System.out.println(submit.get());
System.out.println("over");
single.shutdown();
}
}
Вывод выполнения - только одна строка
in MyCallable
Наблюдая за jstack, вы можете увидеть следующее
"main" prio=5 tid=0x00007fab3f000000 nid=0x1303 waiting on condition [0x0000000107d63000]
java.lang.Thread.State: WAITING (parking)
at sun.misc.Unsafe.park(Native Method)
- parking to wait for <0x00000007aaeed1d8> (a java.util.concurrent.FutureTask)
at java.util.concurrent.locks.LockSupport.park(LockSupport.java:186)
at java.util.concurrent.FutureTask.awaitDone(FutureTask.java:425)
at java.util.concurrent.FutureTask.get(FutureTask.java:187)
at main.lockTest.ExecutorLock.main(ExecutorLock.java:32)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:140)
Locked ownable synchronizers:
- None
..
"pool-1-thread-1" prio=5 tid=0x00007fab3f835800 nid=0x5303 waiting on condition [0x00000001199ee000]
java.lang.Thread.State: WAITING (parking)
at sun.misc.Unsafe.park(Native Method)
- parking to wait for <0x00000007ab0f8698> (a java.util.concurrent.FutureTask)
at java.util.concurrent.locks.LockSupport.park(LockSupport.java:186)
at java.util.concurrent.FutureTask.awaitDone(FutureTask.java:425)
at java.util.concurrent.FutureTask.get(FutureTask.java:187)
at main.lockTest.ExecutorLock$MyCallable.call(ExecutorLock.java:26)
at main.lockTest.ExecutorLock$MyCallable.call(ExecutorLock.java:20)
at java.util.concurrent.FutureTask.run(FutureTask.java:262)
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:745)
Locked ownable synchronizers:
- <0x00000007aaeed258> (a java.util.concurrent.ThreadPoolExecutor$Worker)
Основной поток ожидает завершения FutureTask, а поток в пуле потоков также ожидает завершения FutureTask.
Как видно из реализации кода, основной поток закинул задачу А в пул потоков, а задача А закинула задачу Б в тот же пул потоков, и дождалась завершения В. Так как в пуле всего один поток пул потоков, это будет В результате B застрянет в очереди на блокировку, а A должен дождаться завершения B, а значит, ожидание друг друга приводит к возрождению тупика.
Это явление блокировки из-за того, что выполняющиеся потоки задач ожидают задач в других рабочих очередях, называется взаимоблокировкой голодания потока.
живой замок
Блокировки потока нет, но выполнение не может продолжаться из-за наличия какой-то проблемы.
-
Повтор сообщения. Когда сообщение не может быть обработано, оно все время повторяется, но по какой-то причине синтаксический анализ завершается сбоем из-за неправильного формата сообщения, и оно повторяется снова.
В это время, как правило, необходимо не повторять неисправимые ошибки или ограничивать количество повторных попыток.
-
Потоки, которые взаимодействуют друг с другом, реагируют друг на друга, чтобы изменить свое состояние, что приводит к сбою выполнения. Например, два очень вежливых человека встречаются на одной дороге, уступают друг другу дорогу, но снова встречаются на той же дороге. неоднократно избегайте друг друга
В это время вы можете выбрать случайную уступку, чтобы она имела определенную случайность