了解锁定范围

Understanding lock scope

由此link,我明白了"Since the lock() and unlock() method calls are explicit, we can move them anywhere, establishing any lock scope, from a single line of code to a scope that spans multiple methods"

所以我从上面的说法中理解的是

public class Test {
    Lock l = new ReentrantLock();

    void myMethod1() {
        l.lock();
        // Do my stuff here
    }

    void myMethod2() {
        // Do more stuff here
        l.unlock();
    }
}

所以基本上 1 可以依次调用 method1 和 method2 并假设调用是线程安全的。

不知道是不是上面所说的

如果有人在我已经在执行 method1/method2 对时调用 method2 怎么办?它不会使事情复杂化吗。

我认为应该在函数本身获取和释放锁,然后再从函数返回控制权。我的理解正确吗?

改为考虑这个例子:

public class Test {
    ...
    public void method1() {
       l.lock();
       ...
    }

    public void method2() {
       l.lock();
       ...
       while (l.isHeldByCurrentThread()) {
         l.unlock();
       }
    }
}

此设置意味着一旦线程 A 调用 method1(),线程 B 将在调用任何方法时阻塞,直到线程 A 调用 method2()。因此锁定范围跨越 method1() 的零次或多次调用,然后是 method2().

的单次调用

尽管在实践中我认为编写将锁定范围限制为单个方法或方法的一部分的代码更容易和更清晰。

第一个问题的答案:

What if somebody just calls method2 when i am already executing method1/method2 pair? Doesn't it complicate things.

假设另一个线程在 ReentrantLock 对象上调用 unlock() 方法 然后 IllegalMonitorStateException 将被抛出 。因为线程没有获取锁,当它试图解锁时它会得到异常。
它不会对获取锁的第一个线程的执行或锁定产生任何影响。

  • 相同主题:

    • 锁:如果正在获取锁的同一线程再次尝试获取锁,则锁计数器递增。
    • 解锁:如果正在获取锁的同一线程尝试解锁,则锁计数器递减,一旦锁计数器变为 0,线程就会释放锁。
  • 不同线程:

    • 锁:如果锁被另一个线程持有,则当前线程出于线程调度目的而被禁用并处于休眠状态,直到获得锁,此时锁持有计数设置为 1。
    • 解锁:如果不同的线程在未持有锁时尝试unlock,则会抛出 IllegalMonitorStateException。

这就是 ReentrantLock 锁定和解锁要求您使用 try-catch 或 throw 机制的原因,因为它会抛出异常。

阅读以下摘自 ReentrantLock#unlock()

If the current thread is the holder of this lock then the hold count is decremented. If the hold count is now zero then the lock is released. If the current thread is not the holder of this lock then {@link IllegalMonitorStateException} is thrown.

第二个问题的答案:

I think a lock should be acquired and released in the function itself, before the control is returned from the function. Is my understanding correct?

这就是 ReentrantLock 的全部目的,您可以将锁定机制扩展到其他方法,这是同步块和方法无法做到的。见下文来自ReentrantLock

A reentrant mutual exclusion Lock with the same basic behavior and semantics as the implicit monitor lock accessed using synchronized methods and statements, but with extended capabilities.

What if somebody just calls method2 when i am already executing method1/method2 pair? Doesn't it complicate things.

java.util.concurrent.locks.Lock 是比 synchronized 更强大的机制。电动工具很危险。谨慎使用。

有关详细信息,请参阅@hagrawal 的回答。