经常会被问到wait()方法做了什么
    那很简单:释放锁,开始等待唤醒

    那么,如果wait方法在调用到时候没有加锁,会出现什么情况

    1. public class Solution {
    2. public static void main(String[] args) throws Exception {
    3. Object lock = new Object();
    4. lock.wait();
    5. }
    6. }

    可以看到输出是:

    1. Exception in thread "main" java.lang.IllegalMonitorStateException
    2. at java.lang.Object.wait(Native Method)
    3. at java.lang.Object.wait(Object.java:502)
    4. 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。
    这时可以进去看一下源码

    1. // 直接追到最后抛出异常的地方
    2. protected final boolean tryRelease(int releases) {
    3. // 判断当前线程是否是获取锁的线程
    4. if (Thread.currentThread() != getExclusiveOwnerThread())
    5. throw new IllegalMonitorStateException();
    6. //...
    7. return free;
    8. }

    可以看到,因为await也会释放锁,所以会判断当前线程是否是持锁线程。
    若不是持锁线程,直接抛一个异常出来。
    notify和signal方法也同样,需要在加锁范围内才可以唤醒其他等待线程。