Java 线程获取其他线程已经获取的ReentrantLock
我们的应用程序运行在WebLogic 12c中,正在从队列系统中检索消息,我们从中检索消息的队列配置为FIFO。我们使用Spring来配置检索功能,容器(org.springframework.jms.listener.DefaultMessageListenerContainer)和消息侦听器(org.springframework.jms.core.support.JmsGatewaySupport)都是单例。此外,该容器已默认将WorkManager配置为任务执行器。为了保证消息按照预期的顺序(即消息发送到队列的顺序)进行处理,我们在侦听器中使用了ReentrantLock,并且我们希望消息被逐个检索和处理。侦听器代码如下所示:Java 线程获取其他线程已经获取的ReentrantLock,java,multithreading,reentrantlock,Java,Multithreading,Reentrantlock,我们的应用程序运行在WebLogic 12c中,正在从队列系统中检索消息,我们从中检索消息的队列配置为FIFO。我们使用Spring来配置检索功能,容器(org.springframework.jms.listener.DefaultMessageListenerContainer)和消息侦听器(org.springframework.jms.core.support.JmsGatewaySupport)都是单例。此外,该容器已默认将WorkManager配置为任务执行器。为了保证消息按照预期的
public class JmsReceiveAdapterImpl extends JmsGatewaySupport implements SessionAwareMessageListener {
private final ReentrantLock lock = new ReentrantLock(true);
[...]
public void onMessage(Message rcvMessage, Session session) throws JMSException {
lock.lock();
logger.warn("Lock has been acquired by thread: " + Thread.currentThread().getId());
try {
[...]
} finally {
logger.warn("Lock is going to be released by thread: " + Thread.currentThread().getId());
lock.unlock();
}
}
}
即使两条消息以正确的顺序放置在队列中,并且它们以该顺序被使用(回想一下,队列是FIFO队列),应用程序还是会以某种方式并行处理这两条消息,如以下日志块所示:
Lock has been acquired by thread: 28
Backout count: 1
Message 1 / 1 received from XXX Message ID1 received.
Lock has been acquired by thread: 54
Backout count: 1
Message 1 / 1 received from XXX Message ID2 received.
***** ERROR *****
Lock is going to be released by thread: 54
Lock is going to be released by thread: 28
锁已被线程获取:28
退出计数:1
收到来自XXX的消息1/1收到消息ID1。
线程已获取锁:54
退出计数:1
从XXX收到消息1/1,收到消息ID2。
*****错误*****
锁将由线程释放:54
锁将由线程释放:28
我们为什么会有这种行为?有什么想法吗
非常感谢您的advanced。更改
logger.warn("Lock has been acquired by thread: " + Thread.currentThread().getId());
到
您可能会看到,System.identityHashCode
将是两个不同的数字。如果是同一个对象,则identityHashCode将是相同的。如果它们不同,那就意味着它们是不同的对象
这说明存在多个
ReentrantLock
实例,并且不支持对不同实例的互斥。考虑到ReentrantLock
不起作用的可能性接近于零,我建议您将此
输出到日志,为了确保您的类是一个单例。还要检查您是否没有对从此锁创建的某些条件调用await()
。如果您想绝对确定,可以将锁设置为静态,但从设计角度看,这将是一个灾难,您应该使用logger.debug()而不是logger.warn()。如果您选择warn()是因为debug()消息没有显示在您的日志中,那么学习如何配置log4j是值得的:谢谢大家。user3707125:我将检查侦听器是否为单例,并且应用程序中只有一个实例处于活动状态。talex:不,wait()不会在任何地方调用。斯金尼:这是我最后的资源。詹姆斯:事实上,这个日志是一个定制的日志,出于隐私的原因,我已经在帖子中展示了它。也许这引起了混乱。无论如何,谢谢你的链接。非常感谢你,约翰。我将执行你的建议。一旦我得到结果,我会在这里分享。
logger.warn("Lock has been acquired by thread: " + Thread.currentThread().getId() + " And Object " + System.identityHashCode(this));