了解锁定范围

S K*_* Kr 7 java multithreading reentrantlock

从这个链接,我理解"由于lock()和unlock()方法调用是显式的,我们可以将它们移动到任何地方,建立任何锁定范围,从单行代码到跨越多个方法的范围"

所以我从上面的陈述中理解的是

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

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

    void myMethod2() {
        // Do more stuff here
        l.unlock();
    }
}
Run Code Online (Sandbox Code Playgroud)

所以基本上1可以按顺序调用method1和method2,并假设调用是线程安全的.

我不确定如上所述是否属实.

如果有人在我已经执行method1/method2对时调用method2怎么办?这不是事情的复杂化.

我认为在从函数返回控件之前,应该在函数本身中获取并释放锁.我的理解是否正确?

hag*_*wal 5

回答第一个问题:

如果有人在我已经执行method1/method2对时调用method2怎么办?这不是事情的复杂化.

假设另一个线程调用该对象unlock()上的方法然后将被抛出.因为线程没有获取锁,当它尝试解锁时,它会获得异常.它对正在获取锁的第一个线程的执行或锁定没有任何影响.ReentrantLockIllegalMonitorStateException

  • 相同的线程:

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

    • 锁定:如果锁定由另一个线程保持,则当前线程将被禁用以进行线程调度,并且在获取锁定之前处于休眠状态,此时锁定保持计数设置为1.
    • 解锁:如果不同的线程unlock在没有持有锁时尝试,则抛出IllegalMonitorStateException.

这就是ReentrantLock锁定和解锁要求你拥有try-catch或throw机制的原因,因为它会抛出异常.

请阅读以下摘录 ReentrantLock#unlock()

如果当前线程是此锁的持有者,则保持计数递减.如果保持计数现在为零,则释放锁定. 如果当前线程不是此锁的持有者,则抛出{@link IllegalMonitorStateException}.

回答第二个问题:

我认为在从函数返回控件之前,应该在函数本身中获取并释放锁.我的理解是否正确?

这就是整个目的ReentrantLock,您可以将锁定机制扩展到其他方法,而这些方法不能用于同步块和方法.请参阅下面的ReentrantLock

可重入互斥锁具有与使用同步方法和语句访问的隐式监视器锁相同的基本行为和语义,但具有扩展功能.