从这个link,我理解“由于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();
}
}
所以基本上1可以按顺序调用method1和method2,并假设调用是线程安全的。
我不确定这是否如上所述。
如果有人在我已经执行method1 / method2对时调用method2怎么办?这不会使事情变得复杂。
我认为在从函数返回控件之前,应该在函数本身中获取并释放锁。我的理解是否正确?
答案 0 :(得分:5)
回答第一个问题:
如果有人在我执行时只调用method2怎么办? method1 / method2对?这不会使事情变得复杂。
假设另一个线程调用unlock()
对象上的ReentrantLock
方法,然后IllegalMonitorStateException
将被抛出。因为线程没有获取锁定,当它尝试解锁时,它会获得异常
对获取锁定的第一个线程的执行或锁定没有任何影响。
相同主题:
不同主题:
unlock
,则抛出IllegalMonitorStateException。这就是ReentrantLock
锁定和解锁要求你拥有try-catch或throw机制的原因,因为它会抛出异常。
请阅读以下ReentrantLock#unlock()
如果当前线程是此锁的持有者,则保持 计数递减。如果保持计数现在为零则锁定为 释放。 如果当前线程不是此锁的持有者那么 抛出{@link IllegalMonitorStateException} 。
回答第二个问题:
我认为应该在函数本身中获取并释放锁, 在从函数返回控件之前。是我的理解 正确的吗?
这是ReentrantLock
的全部目的,您可以将锁定机制扩展到其他方法,而使用synchronized块和方法则无法做到这一点。请参阅下面的ReentrantLock
具有相同基本行为的重入互斥锁定 语义作为使用synchronized访问的隐式监视器锁 方法和陈述,但具有扩展功能。
答案 1 :(得分:1)
请考虑这个例子:
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()
。
虽然在实践中我会认为编写将锁定范围限制为单个方法或方法的一部分的代码会更容易和更清晰。