经常会被问到wait()方法做了什么
那很简单:释放锁,开始等待唤醒
那么,如果wait方法在调用到时候没有加锁,会出现什么情况
public class Solution {
public static void main(String[] args) throws Exception {
Object lock = new Object();
lock.wait();
}
}
可以看到输出是:
Exception in thread "main" java.lang.IllegalMonitorStateException
at java.lang.Object.wait(Native Method)
at java.lang.Object.wait(Object.java:502)
at leetcode.Solution.main(Solution.java:27)
wait本身是一个native的方法,并不能看到实际实现。
但是从异常名字可以看出来,IllegalMonitorStateException,wait方法内部肯定和monitor有关。
之前提到过,每个对象都有一个monitor,对对象上锁就是持有这个monitor。
那么wait方法会抛出这个异常也就理所当然了,此时并没有获取到monitor对象,那么wait也就没发释放锁。
而java中的另一种锁是ReentrantLock。
ReentrantLock的wait方法是Condition类中的await()
同样,在没有lock的时候直接调用condition.await()也会抛出IllegalMonitorStateException。
这时可以进去看一下源码
// 直接追到最后抛出异常的地方
protected final boolean tryRelease(int releases) {
// 判断当前线程是否是获取锁的线程
if (Thread.currentThread() != getExclusiveOwnerThread())
throw new IllegalMonitorStateException();
//...
return free;
}
可以看到,因为await也会释放锁,所以会判断当前线程是否是持锁线程。
若不是持锁线程,直接抛一个异常出来。
notify和signal方法也同样,需要在加锁范围内才可以唤醒其他等待线程。