线程饥饿死锁
正在执行任务的线程都由于等待其他处于任务队列中的任务而阻塞,这就是线程饥饿死锁,线程池中的任务需要无限期地等待一些必须由池中其他任务才能提供的资源或条件,而池中又没有空余线程来执行其他任务。
1,父线程等待子线程返回值
public class DeadLockDemo {
//单线程线程池
private static ExecutorService exec = Executors.newSingleThreadExecutor();
public static class DeadLockTask implements Callable<String> {
@Override
public String call() throws Exception {
Future<String> submit1 = exec.submit(() -> {
System.err.println("submit1");
return "submit1";
});
//发生死锁 -- 由于任务在等待子任务的结果
return submit1.get();
}
}
public static void main(String[] args) throws Exception {
// 此处必然死锁
Future<String> submit = exec.submit(new DeadLockTask());
try {
submit.get();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
}
原理图
唯一线程在等待main,main在等待submit1,submit1在等待唯一线程,三角等待 => 死锁
2,栅栏数量大于线程池最大数量
/**
* 当线程池规模小,任务数量大于线程数量时
* 通过栅栏等待线程结束时将造成死锁
*/
public class DeadLockDemo2 {
private static ExecutorService exec = Executors.newFixedThreadPool(2);
private static CyclicBarrier barrier = new CyclicBarrier(3);
/**
* 线程池创建的两个线程任务都将被栅栏阻塞,而栅栏需要达到三个任务才能取消,此时就将造成线程死锁
* @param args
*/
public static void main(String[] args) {
for (int i = 0; i < 3; i++) {
int finalI = i;
exec.execute(()->{
System.err.println(finalI);
try {
barrier.await();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
});
}
}
}
原理图
栅栏需要等待指定协议数量线程到达后才释放阻塞