使用Disruptor BlockingWaitStrategy遭遇死锁dead lock

简介: 使用Disruptor BlockingWaitStrategy遭遇死锁dead lock

发现跑了半天的game server登录不了,简单jstack了下,发现登录线程 game-bus_init-X 被堵塞了,一直堵在抛出登录事件上,原因是

Affects AAffects Version:3.3.2  Fix version:3.3.6
JDK 1.8
Cause
: Nope this is not resolved by dropping the events. Ring Buffer Works on Producer and Consumer Thread Model.This issue actually happened due to signal missed by consumer. As per LMAX disruptor signal miss should not happen.

这不是通过删除事件来解决。 环形缓冲区在生产者和消费者线程模型上工作。这个问题实际上是由于消费者错过信号而发生的。 根据LMAX中断器信号缺失不应该发生。



Solution:by mikeb01

I added support for re-signalling the listeners if the producer encounters a full ring buffer, so if the signal happened to be lost somehow (not convinced that it can be) then it will be on the next attempted publication.

如果生产者遇到一个已塞满的环形缓冲区,我添加了对重新发信号通知监听器的支持,所以如果信号偶然丢失(不确信是不是这个原因),那么它将在下一次重新发布。


If it detects that the ring buffer is full it will re-signal the wait strategy, this should unstick the consumer if it happened to miss a signal.

如果它检测到环形缓冲区已满,它将重发信号的等待策略,如果它碰巧错过一个信号,这应该解锁消费者。

也可以改用Add LiteTimeoutBlockingWaitStrategy

"game-bus_init-3" #69 daemon prio=5 os_prio=0 tid=0x00007f9ba1cf1800 nid=0x1113 waiting on condition [0x00007f9af25e8000]
   java.lang.Thread.State: WAITING (parking)
  at sun.misc.Unsafe.park(Native Method)
  - parking to wait for  <0x00000000d5054d20> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
  at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
  at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2039)
  at com.lmax.disruptor.BlockingWaitStrategy.waitFor(BlockingWaitStrategy.java:45)
  at com.lmax.disruptor.ProcessingSequenceBarrier.waitFor(ProcessingSequenceBarrier.java:55)
  at com.lmax.disruptor.BatchEventProcessor.run(BatchEventProcessor.java:123)
  at java.lang.Thread.run(Thread.java:745)
"game-bus_init-2" #68 daemon prio=5 os_prio=0 tid=0x00007f9ba1cef800 nid=0x1112 runnable [0x00007f9af26e8000]
   java.lang.Thread.State: TIMED_WAITING (parking)
  at sun.misc.Unsafe.park(Native Method)
  at java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:338)
  at com.lmax.disruptor.MultiProducerSequencer.next(MultiProducerSequencer.java:136)
  at com.lmax.disruptor.MultiProducerSequencer.next(MultiProducerSequencer.java:105)
  at com.lmax.disruptor.RingBuffer.next(RingBuffer.java:246)
  at com.lingyu.common.message.BalanceBusinessExecutor$ExecutorPoolGroup$Executor.execute(BalanceBusinessExecutor.java:156)
  at com.lingyu.game.service.event.EventManager.asyncCall(EventManager.java:84)
  at com.lingyu.game.service.event.AbEvent.advancedAsyncCall(AbEvent.java:114)
  at com.lingyu.game.service.event.AbEvent.dispatch(AbEvent.java:73)
  at com.lingyu.game.service.event.LoginGameEvent.publish(LoginGameEvent.java:130)
  at com.xianling.public_.nodecontrol.service.impl.NodeControlServiceImpl.login(NodeControlServiceImpl.java:55)
  at com.lingyu.game.action.bus.LoginAction.loginGame(LoginAction.java:254)
  at com.lingyu.game.action.bus.LoginActionMethodAccess.invoke(Unknown Source)
  at com.lingyu.common.message.MessageResolver.execute(MessageResolver.java:46)
  at com.lingyu.common.message.MessageMediator.execute(MessageMediator.java:75)
  at com.lingyu.common.message.ExecutorRunnablePool$RunnableImpl.run(ExecutorRunnablePool.java:87)
  at com.lingyu.common.message.GameEventHandler.onEvent(GameEventHandler.java:20)
  at com.lingyu.common.message.GameEventHandler.onEvent(GameEventHandler.java:11)
  at com.lmax.disruptor.BatchEventProcessor.run(BatchEventProcessor.java:128)
  at java.lang.Thread.run(Thread.java:745)
"game-bus_init-1" #67 daemon prio=5 os_prio=0 tid=0x00007f9ba1ced800 nid=0x1111 runnable [0x00007f9af27e9000]
   java.lang.Thread.State: TIMED_WAITING (parking)
  at sun.misc.Unsafe.park(Native Method)
  at java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:338)
  at com.lmax.disruptor.MultiProducerSequencer.next(MultiProducerSequencer.java:136)
  at com.lmax.disruptor.MultiProducerSequencer.next(MultiProducerSequencer.java:105)
  at com.lmax.disruptor.RingBuffer.next(RingBuffer.java:246)
  at com.lingyu.common.message.BalanceBusinessExecutor$ExecutorPoolGroup$Executor.execute(BalanceBusinessExecutor.java:156)
  at com.lingyu.game.service.event.EventManager.asyncCall(EventManager.java:84)
  at com.lingyu.game.service.event.AbEvent.advancedAsyncCall(AbEvent.java:114)
  at com.lingyu.game.service.event.AbEvent.dispatch(AbEvent.java:73)
  at com.lingyu.game.service.event.LoginGameEvent.publish(LoginGameEvent.java:130)
  at com.xianling.public_.nodecontrol.service.impl.NodeControlServiceImpl.login(NodeControlServiceImpl.java:55)
  at com.lingyu.game.action.bus.LoginAction.loginGame(LoginAction.java:254)
  at com.lingyu.game.action.bus.LoginActionMethodAccess.invoke(Unknown Source)
  at com.lingyu.common.message.MessageResolver.execute(MessageResolver.java:46)
  at com.lingyu.common.message.MessageMediator.execute(MessageMediator.java:75)
  at com.lingyu.common.message.ExecutorRunnablePool$RunnableImpl.run(ExecutorRunnablePool.java:87)
  at com.lingyu.common.message.GameEventHandler.onEvent(GameEventHandler.java:20)
  at com.lingyu.common.message.GameEventHandler.onEvent(GameEventHandler.java:11)
  at com.lmax.disruptor.BatchEventProcessor.run(BatchEventProcessor.java:128)
  at java.lang.Thread.run(Thread.java:745)
"game-bus_init-0" #66 daemon prio=5 os_prio=0 tid=0x00007f9ba1ceb800 nid=0x1110 runnable [0x00007f9af28eb000]
   java.lang.Thread.State: TIMED_WAITING (parking)
  at sun.misc.Unsafe.park(Native Method)
  at java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:338)
  at com.lmax.disruptor.MultiProducerSequencer.next(MultiProducerSequencer.java:136)
  at com.lmax.disruptor.MultiProducerSequencer.next(MultiProducerSequencer.java:105)
  at com.lmax.disruptor.RingBuffer.next(RingBuffer.java:246)
  at com.lingyu.common.message.BalanceBusinessExecutor$ExecutorPoolGroup$Executor.execute(BalanceBusinessExecutor.java:156)
  at com.lingyu.game.service.event.EventManager.asyncCall(EventManager.java:84)
  at com.lingyu.game.service.event.AbEvent.advancedAsyncCall(AbEvent.java:114)
  at com.lingyu.game.service.event.AbEvent.dispatch(AbEvent.java:73)
  at com.lingyu.game.service.event.LoginGameEvent.publish(LoginGameEvent.java:130)
  at com.xianling.public_.nodecontrol.service.impl.NodeControlServiceImpl.login(NodeControlServiceImpl.java:55)
  at com.lingyu.game.action.bus.LoginAction.loginGame(LoginAction.java:254)
  at com.lingyu.game.action.bus.LoginActionMethodAccess.invoke(Unknown Source)
  at com.lingyu.common.message.MessageResolver.execute(MessageResolver.java:46)
  at com.lingyu.common.message.MessageMediator.execute(MessageMediator.java:75)
  at com.lingyu.common.message.ExecutorRunnablePool$RunnableImpl.run(ExecutorRunnablePool.java:87)
  at com.lingyu.common.message.GameEventHandler.onEvent(GameEventHandler.java:20)
  at com.lingyu.common.message.GameEventHandler.onEvent(GameEventHandler.java:11)
  at com.lmax.disruptor.BatchEventProcessor.run(BatchEventProcessor.java:128)
  at java.lang.Thread.run(Thread.java:745)
"game-bus_cache-3" #65 daemon prio=5 os_prio=0 tid=0x00007f9ba1cea000 nid=0x110f waiting on condition [0x00007f9af29ec000]
   java.lang.Thread.State: WAITING (parking)
  at sun.misc.Unsafe.park(Native Method)
  - parking to wait for  <0x00000000d5054d80> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
  at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
  at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2039)
  at com.lmax.disruptor.BlockingWaitStrategy.waitFor(BlockingWaitStrategy.java:45)
  at com.lmax.disruptor.ProcessingSequenceBarrier.waitFor(ProcessingSequenceBarrier.java:55)
  at com.lmax.disruptor.BatchEventProcessor.run(BatchEventProcessor.java:123)
  at java.lang.Thread.run(Thread.java:745)
"game-bus_cache-2" #64 daemon prio=5 os_prio=0 tid=0x00007f9ba1ce8000 nid=0x110e waiting on condition [0x00007f9af2aed000]
   java.lang.Thread.State: WAITING (parking)
  at sun.misc.Unsafe.park(Native Method)
  - parking to wait for  <0x00000000d5054db0> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
  at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
  at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2039)
  at com.lmax.disruptor.BlockingWaitStrategy.waitFor(BlockingWaitStrategy.java:45)
  at com.lmax.disruptor.ProcessingSequenceBarrier.waitFor(ProcessingSequenceBarrier.java:55)
  at com.lmax.disruptor.BatchEventProcessor.run(BatchEventProcessor.java:123)
  at java.lang.Thread.run(Thread.java:745)
"game-bus_cache-1" #63 daemon prio=5 os_prio=0 tid=0x00007f9ba1ce6000 nid=0x110d waiting on condition [0x00007f9af2bee000]
   java.lang.Thread.State: WAITING (parking)
  at sun.misc.Unsafe.park(Native Method)
  - parking to wait for  <0x00000000d50e2650> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
  at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
  at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2039)
  at com.lmax.disruptor.BlockingWaitStrategy.waitFor(BlockingWaitStrategy.java:45)
  at com.lmax.disruptor.ProcessingSequenceBarrier.waitFor(ProcessingSequenceBarrier.java:55)
  at com.lmax.disruptor.BatchEventProcessor.run(BatchEventProcessor.java:123)
  at java.lang.Thread.run(Thread.java:745)
"game-bus_cache-0" #62 daemon prio=5 os_prio=0 tid=0x00007f9ba1ce4000 nid=0x110c runnable [0x00007f9af2cee000]
   java.lang.Thread.State: TIMED_WAITING (parking)
  at sun.misc.Unsafe.park(Native Method)
  at java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:338)
  at com.lmax.disruptor.MultiProducerSequencer.next(MultiProducerSequencer.java:136)
  at com.lmax.disruptor.MultiProducerSequencer.next(MultiProducerSequencer.java:105)
  at com.lmax.disruptor.RingBuffer.next(RingBuffer.java:246)
  at com.lingyu.common.message.BalanceBusinessExecutor$ExecutorPoolGroup$Executor.execute(BalanceBusinessExecutor.java:156)
  at com.lingyu.game.service.event.EventManager.asyncCall(EventManager.java:84)
  at com.lingyu.game.service.event.AbEvent.advancedAsyncCall(AbEvent.java:114)
  at com.lingyu.game.service.event.AbEvent.dispatch(AbEvent.java:73)
  at com.lingyu.game.service.event.MoneyIncrEvent.publish(MoneyIncrEvent.java:65)
  at com.lingyu.game.service.role.RoleManager.incrCoin(RoleManager.java:2369)
  at com.lingyu.game.service.role.CoinMoneyOperation.incr(CoinMoneyOperation.java:19)
  at com.lingyu.game.service.money.MoneyManager.incr(MoneyManager.java:203)
  - locked <0x00000000ebf8eaa8> (a [Ljava.lang.Byte;)
  at com.lingyu.game.service.money.MoneyManager.incr(MoneyManager.java:136)
  at com.lingyu.game.service.money.MoneyManager.incr(MoneyManager.java:171)
  at com.lingyu.game.action.bus.RoleAction.addMoney(RoleAction.java:906)
  at com.lingyu.game.action.bus.RoleActionMethodAccess.invoke(Unknown Source)
  at com.lingyu.common.message.MessageResolver.execute(MessageResolver.java:35)
  at com.lingyu.common.message.MessageMediator.execute(MessageMediator.java:69)
  at com.lingyu.common.message.ExecutorRunnablePool$RunnableImpl.run(ExecutorRunnablePool.java:85)
  at com.lingyu.common.message.GameEventHandler.onEvent(GameEventHandler.java:20)
  at com.lingyu.common.message.GameEventHandler.onEvent(GameEventHandler.java:11)
  at com.lmax.disruptor.BatchEventProcessor.run(BatchEventProcessor.java:128)
  at java.lang.Thread.run(Thread.java:745)

参考文章:

Dead lock observed in BlockingWaitStrategy

Dead lock observed in BlockingWaitStrategy in Log4J

Add LiteTimeoutBlockingWaitStrategy

后发现又重现这个问题了,原来是因为待处理的事件超过了ringbuff size的上限,导致事件又被覆盖导致了,无法处理。

目录
相关文章
|
2月前
|
安全 Java 开发者
Java多线程中的`wait()`、`notify()`和`notifyAll()`方法,探讨了它们在实现线程间通信和同步中的关键作用
本文深入解析了Java多线程中的`wait()`、`notify()`和`notifyAll()`方法,探讨了它们在实现线程间通信和同步中的关键作用。通过示例代码展示了如何正确使用这些方法,并分享了最佳实践,帮助开发者避免常见陷阱,提高多线程程序的稳定性和效率。
54 1
|
3月前
|
存储 安全 算法
Wound/Wait死锁安全的互斥锁设计 【ChatgGPT】
Wound/Wait死锁安全的互斥锁设计 【ChatgGPT】
|
6月前
|
Java
JAVA多线程的“心灵感应”:wait()与notify()的秘密
【6月更文挑战第20天】Java多线程中,`wait()`和`notify()`是线程间协作的关键。它们充当线程间的通信桥梁,使得线程能感知对方状态。例如,生产者线程在资源满时`wait()`,消费者线程消费后`notify()`或`notifyAll()`,确保资源有效利用且避免冲突。简化的代码示例展示了这种同步机制,线程通过等待和唤醒操作实现“心灵感应”般的协同工作。
34 3
|
7月前
|
安全 算法 关系型数据库
线程安全--深入探究线程等待机制和死锁问题
线程安全--深入探究线程等待机制和死锁问题
228 1
|
7月前
|
Java
Java多线程:什么是死锁(Deadlock)?
Java多线程:什么是死锁(Deadlock)?
97 0
JUC学习(三):synchronized和Lock实现线程间通信(包含虚假唤醒的讲解)
JUC学习(三):synchronized和Lock实现线程间通信(包含虚假唤醒的讲解)
JUC学习(三):synchronized和Lock实现线程间通信(包含虚假唤醒的讲解)
|
安全 Java
Java并发编程之Wait和Notify
Java并发编程之Wait和Notify
135 0
Java并发编程之Wait和Notify
|
算法 Java 程序员
Java多线程之死锁问题,wait和notify
Java多线程之死锁问题,wait和notify
259 0
Java多线程之死锁问题,wait和notify
|
安全 Java
Java并发编程之Lock(同步锁、死锁)
这篇文章是接着我上一篇文章来的。
133 0
|
安全 Java
Java多线程06—用Lock锁解决线程的安全问题
Java多线程06—用Lock锁解决线程的安全问题
146 0
Java多线程06—用Lock锁解决线程的安全问题