我很难理解ReentrantLock.lock()
的行为我有以下课程
import java.util.concurrent.locks.*;
class BlockingClass {
private Lock lock = new ReentrantLock();
private Condition condition = lock.newCondition();
public void a() {
lock.lock();
System.out.println("called in method a(): lock()");
try {
System.out.println("called in method a(): await()");
condition.await();
}
catch (InterruptedException e) {}
finally {
lock.unlock();
System.out.println("called in method a(): unlock() ");
}
}
public void b() {
lock.lock();
System.out.println("called in method b(): lock()");
System.out.println("called in method b(): signalAll()");
condition.signalAll();
lock.unlock();
System.out.println("called in method b(): unlock() ");
}
}
我使用以下测试运行:
class BlockingClassTest {
public static void main(String[] args) throws InterruptedException {
final BlockingClass blockingClass = new BlockingClass();
new Thread() {
public void run() {
System.out.println("Thread1 calling a()");
blockingClass.a();
}
}.start();
Thread.sleep(1000);
new Thread() {
public void run() {
System.out.println("Thread2 calling b()");
blockingClass.b();
}
}.start();
}
}
我原本预计会陷入僵局。一旦a()方法调用lock.lock(),我希望任何调用b()方法的人都必须等待b的lock.lock(),直到调用a()的线程调用lock.unlock()。但是因为a()正在等待b()调用condition.signalAll(),所以这两种方法都应该永远被阻止。
相反,这是我在控制台中得到的输出:
Thread1 calling a()
called in method a(): lock()
called in method a(): await()
Thread2 calling b()
called in method b(): lock()
called in method b(): signalAll()
called in method a(): unlock()
called in method b(): unlock()
我对lock()和unlock()的正确使用和功能有什么误解?
答案 0 :(得分:5)
你没有误解ReentrantLock
,你误解了Condition
。 Condition
绑定到一个锁,Condition.await()
将有效解锁,检查并等待,然后重新锁定锁。请参阅Condition.await()
。
在a()
,lock()
和await()
之间以及await()
和unlock()
的回复之间,您的锁定正如您所期望的那样。在await()
的来电中,Condition
正在管理它。
这是“条件变量”的一般概念的一部分;这就是为什么你找到的任何线程库将某种锁与一个条件相关联(例如在POSIX C中,pthread_cond_wait
需要一个条件变量和一个互斥锁。)
查看关于condition variables的维基百科文章,它详细解释了这种行为及其原因。
答案 1 :(得分:2)
您对condition.await();
的调用将释放锁定,使线程处于wait
状态,因此线程b可以获得锁定。
a()
方法会在b()
释放锁定后继续运行,因为您已发出信号。
答案 2 :(得分:1)
答案已经给出,但我认为我只引用javadocs for Condition.await()
来提供更多背景信息:
使当前线程等到信号通知或中断为止。
与此条件关联的锁是原子释放,并且当前线程因线程调度而被禁用,并且在发生以下四种情况之一之前处于休眠状态:
- 其他一些线程调用此Condition的signal方法,当前线程恰好被选为要被唤醒的线程;或
- 其他一些线程为此Condition调用signalAll方法;或
- 其他一些线程中断当前线程,并支持线程挂起中断;或
- 发生“虚假唤醒”。
醇>在所有情况下,在此方法返回之前,当前线程必须重新获取与此条件关联的锁。当线程返回时,保证保持此锁定。
因此,当您调用condition.await()
时,它会释放锁定,允许其他线程进入锁定部分。这与Object.wait()
代码块内的synchronized
行为相同。