java - 线程获取已被其他线程获取的 ReentrantLock

标签 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 队列),不知何故,这两条消息由应用程序并行处理,如图所示在以下日志 block 中:

    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

为什么我们会出现这种行为?有什么想法吗?

非常感谢您。

最佳答案

改变

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 实例,并且不支持差异实例上的互斥。

关于java - 线程获取已被其他线程获取的 ReentrantLock,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30920167/

相关文章:

java - ReentrantLock 与 CompletableFuture

java - Hibernate TransientPropertyValueException 在保存数据时

Java 线程工作组性能与嵌入式循环性能

java - 如何模拟由MyBatis初始化的接口(interface)的引用?

IOS:后台操作期间主线程变慢

c# - 为什么使用 Task.ContinueWith 会损害我的程序的响应能力?

java - 没有公平性的 DelayQueue 是否有问题?

java - Android 游戏循环中的高级并发

java - 依赖项(Jar 文件)中的类未解析,导致编译错误

java - 如何在 Java 中将颜色名称转换为十六进制值