线程获取已由其他线程获取的ReentrantLock

时间:2015-06-18 15:52:06

标签: java multithreading reentrantlock

我们在WebLogic 12c中运行的应用程序正在从排队系统中检索消息,我们从中检索消息的队列被配置为FIFO。我们使用Spring来配置检索功能,容器(org.springframework.jms.listener.DefaultMessageListenerContainer)和消息监听器(org.springframework.jms.core.support.JmsGatewaySupport)都是单例。此外,该容器默认将WorkManager配置为任务执行程序。为了保证消息按预期的顺序(它们如何发送到队列的顺序)处理,我们在侦听器中使用ReentrantLock,我们期望逐个检索和处理消息。监听器代码如下:

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

为什么我们会获得此行为?有什么想法吗?

非常感谢你。

1 个答案:

答案 0 :(得分:3)

更改

logger.warn("Lock has been acquired by thread: " + Thread.currentThread().getId());

logger.warn("Lock has been acquired by thread: " + Thread.currentThread().getId() + " And Object " + System.identityHashCode(this));

您可能会看到System.identityHashCode将是两个不同的数字。如果它是同一个对象,则identityHashCode将是相同的。如果它们不同,那意味着它们是不同的对象。

它告诉您的是,有多个ReentrantLock实例,并且不支持差异实例上的互斥。