我的印象是wait()释放了所有锁,但是我发现这篇文章说

“在同步方法内调用等待是获取固有锁的一种简单方法”

请说明我有点困惑。

http://docs.oracle.com/javase/tutorial/essential/concurrency/guardmeth.html

最佳答案

“在同步方法内调用等待是获取固有锁的一种简单方法”

这句话是错误的,它是文档错误。

以同步方法输入时,线程获得内部锁。
同步方法内部的线程被设置为锁的所有者,并且处于 RUNNABLE 状态。
任何尝试输入锁定方法的线程都将成为 BLOCKED

当线程调用等待时,它将释放当前的对象锁(保留其他对象的所有锁),然后进入 WAITING 状态。

当其他某个线程调用同一对象上的notify或notifyAll时,第一个线程将状态从WAITING更改为BLOCKED,
通知线程不会自动重新获取锁或变为RUNNABLE,实际上,它必须与所有其他阻塞线程争夺锁。

WAITING和BLOCKED状态都阻止线程运行,但是它们有很大的不同。

必须通过其他线程的通知将等待线程显式转换为阻塞线程。

等待永远不会直接进入可运行状态。

当RUNNABLE线程释放锁定(通过离开监视器或等待)时,BLOCKED线程之一将自动取代其位置。

综上所述,线程在进入等待之后进入同步方法或重新进入同步方法时都获得了锁。

public synchronized guardedJoy() {
    // must get lock before entering here
    while(!joy) {
        try {
            wait(); // releases lock here
            // must regain the lock to reentering here
        } catch (InterruptedException e) {}
    }
    System.out.println("Joy and efficiency have been achieved!");
}

09-06 07:37