【问题标题】:java ReentrantLock tryLock() misunderstandingjava ReentrantLock tryLock() 误解
【发布时间】:2021-10-18 21:08:53
【问题描述】:
    ReentrantLock l = new ReentrantLock(true);
            Reader[] readers = new Reader[2];
    
            for (int i = 0; i < readers.length; i++) {
                readers[i] = new Reader(l);
            }
            for (int i = 0; i < readers.length; i++) {
                readers[i].start();
            }

public class Reader extends Thread {

    private ReentrantLock l;

    public Reader(ReentrantLock l) {
        this.l = l;
    }

    @Override
    public void run() {
        try {
              l.tryLock();
            for (int i = 0; i < 5; i++) {
                System.out.println(Thread.currentThread().getName() + " i =  " + i);
                Thread.sleep(500);
            }
//            l.unlock(); // although it commented the code not hanged why?
                   } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

根据我对 tryLock() 的理解,如果它没有被另一个线程持有,则获取锁并立即返回在我的情况下,我有两个线程假设 thread_0 获得锁现在我有两个问题: Q1:为什么thread_1在l.tryLock()之后还是进入了临界区,不是被thread_0锁住了吗? Q2:是不是因为thread_0没有释放锁而导致我的代码被挂起? #谢谢提前

【问题讨论】:

  • 你必须检查返回值。如果tryLock() 返回 false,则说明您没有获得锁。
  • @shmosel 假设我不检查并且 thread_0 来执行 l.tryLock() 并且它返回 true 那么为什么 thread_1 仍然访问我的关键部分不是我的关键部分被 thread_0 锁定为 l。尝试锁定();返回真
  • @ahmedahmed 如果您的代码进入一个部分而没有确保它首先持有锁,那么根据定义,该部分不是一个关键部分。所以你实际上并没有临界区,因为如果tryLock 失败,线程可以在不持有锁的情况下进入该区。
  • 如果tryLock() 被阻塞直到锁被释放,它与lock() 没有什么不同。
  • @DavidSchwartz 不是 l.tryLock();如果它返回 true == l.lock();

标签: java multithreading reentrantlock


【解决方案1】:

您的代码正在进入临界区,因为 tryLock() 不是阻塞函数,它会立即返回 true 或 false,并继续执行下面的“临界区”代码 sn-p。

在 tryLock() 的文档中你可以阅读

如果锁被另一个线程持有,那么这个方法将返回 立即使用值为 false。

所以你需要调用lock()方法,它会一直等到锁被另一个读卡器释放。

【讨论】: