线程饥饿死锁问题排查

摘要:内外层异步使用同一线程池执行任务导致线程数不够,产生线程死锁

问题:

  1. 某台机器查询接口半夜12点有问题,当时同事将问题机器拉出,并进行dump

  2. 由错误日志可以得出是线程的任务队列满导致任务丢弃报错

  3. 从错误日志不能看出具有哪个线程有问题,通过线程统计线程数量看出是query_callback线程池,然后看监控发现队列确实满了。

行动:

  1.  先观察拉取后的线程栈,发现线程全部是WAITING状态,线程被阻塞在业务代码的异步的get方法上。
  2. 发现代码使用了嵌套的completableFuture.thenApplyAsync,在外层thenApplyAsync的代码内部使用了return返回了另一completableFuture的thenApplyAsync,并且使用了同一executor
  3. 通过分析得出所有线程阻塞原因:

    1. 外层异步和内层异步使用同一线程池

    2. 在某个时间范围内,线程池的所有活跃线程都去执行外部异步调用,导致可用线程数为0

    3. 每个外层异步都会从线程池中申请一个线程执行内层异步,由于此时已经没有线程,内层异步的任务被排入任务队列中,没有执行

    4. 外层异步会在内层异步的get方法处等待,而内层异步等待外层异步完成释放线程,因此进入死锁

  4. 解决:

    1. 使用线程隔离:内外层使用不同线程池

  5. 效果:线程死锁解决,线程池任务队列满导致抛出的异常不再产生

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值