java - ReentrantLock 始终由同一线程锁定和解锁

标签 java multithreading reentrantlock

我正在尝试在多线程上实现可重入锁,但由于某种原因,同一线程解锁然后再次锁定,导致始终运行相同的线程,因此执行相同的操作。

下面是线程如何产生的代码

IntStream.range(0,(NUMBER_OF_THREADS)).forEach(index ->{
            boolean operation = (index % 2 == 0) ? true : false;
            Thread t = new Thread(new Client(operation,this));
            t.start();
});

这是线程的 run 函数的工作原理

@Override
public void run() {
    while(!Thread.interrupted()) {
        System.out.println("Trying to acquire lock : " + main.getLock().tryLock()
                + " thread id " + Thread.currentThread().getName());
       // if (main.getLock().tryLock()) {
        try {
            main.getLock().lock();
            if(main.getLock().isHeldByCurrentThread()) {
                System.out.println("Lock held by this thread " + main.getLock().isHeldByCurrentThread()
                        + " thread id : " + Thread.currentThread().getName());
                if (operation) {
                    main.getcAaccount().deposit(1);
                } else {
                    main.getcAaccount().withdraw(2);
                }
                Thread.currentThread().sleep(3000);
            }
        } catch (InterruptedException e) {
                e.printStackTrace();
        } finally {
            System.out.println("Thread id : " + Thread.currentThread().getName() + " unlocking");
            main.getLock().unlock();//always have the unlock part here to ensure it unlock
        }
}

它正确地打印出其他 5 个线程正在尝试获取锁并失败,然后线程 id...正在解锁...并且立即再次锁定同一线程,即使它应该处于 sleep 状态。

我是否错过了这个逻辑场景中的任何内容?

提前谢谢您。

编辑建议修复的屏幕截图。 Still, same thread id unlocks and locks immediately

最佳答案

重入要求每次锁定后都进行后续解锁。例如,如果我调用 lock.lock() 三次,则预计我也会调用 lock.unlock() 三次。在这一系列事件发生之前,ReentrantLock 不会认为自己已解锁。

您没有意识到,lock.tryLock() 如果成功,其行为本质上就像调用 lock.lock()。因此,通过锁定两次,您还需要解锁两次。在您的代码示例中,您仅解锁一次,因此最初锁定的线程在技术上仍然拥有该锁。

修复它应该很简单,您可以从代码中删除第二个 lock.lock() 并且互斥应该仍然有效。或者,如果您需要锁定锁,请将 lock.tryLock() 替换为 lock.lock()

根据您的编辑,您通过删除额外的锁修复了一个问题,但现在您遇到了计时问题。您实际上并不需要 tryLock。您可以将其替换为 lock,因为如果已持有锁,则 lock 调用将挂起线程并阻塞(最终在调用解锁时唤醒)。

关于java - ReentrantLock 始终由同一线程锁定和解锁,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55163310/

相关文章:

java - 有什么办法可以防止字段在 jackson 中反序列化吗?

java - 曲线下面积 - 一维数组 (Java)

c++ - Alpha-Beta "breaking"阿姆达尔定律?

java - 扩展 vert.x 中的工作池

Java锁定条件等待并通知: IllegalMonitorStateException

java - lock.tryLock() 线程安全吗?

java - ReentrantLock 实际使用 lockInterruptibly

Java版本控制

java - 枚举中的 getResources()——Android Studio

multithreading - 如何优化每核心数的线程数