Java 多线程问题
为什么使用 notify 和 notifyAll 的时候要先获得锁?
为什么使用 notify 和 notifyAll 的时候要先获得锁?
你想想
1. 为啥要用锁,不用锁会出啥问题 (原子性)
2. 面对这个问题 怎么用 notify 去解决 (线程等待)
如果确实要线程等待
一般不用 notify 用 LockSupport
> Every object, in addition to having an associated monitor, has an associated *wait set*. A wait set is a set of threads.
>
> When an object is first created, its wait set is empty. **Elementary actions that add threads to and remove threads from wait sets are atomic**. Wait sets are manipulated solely through the methods `Object.wait`, `Object.notify`, and `Object.notifyAll`.
>
> Ref: https://docs.oracle.com/javase/specs/jls/se8/html/jls-17.html
简单来说,当对象创建时,会顺带创建 Monitor 和 Wait Set,这些应该是在 C 语言层面去创建的。然后它告诉我们对 Wait Set 的操作都是 Atomic 的,这就能解释,为什么 wait 和 notify 必须获得锁,因为没有锁,就没办法保证对 wait set 的操作是原子的。
Just as each Java object can act as a lock, each object can also act as a condition queue, and the wait, notify, and notifyAll methods in Object constitute the API for intrinsic condition queues. An object’s intrinsic lock and its intrinsic condition queue are related: in order to call any of the condition queue methods on object X, you must hold the lock on X. This is because the mechanism for waiting for state-based conditions is necessarily tightly bound to the mechanism for preserving state consistency: you cannot wait for a condition unless you can examine the state, and you cannot release another thread from a condition wait unless you can modify the state.
Object.wait atomically releases the lock and asks the OS to suspend the current thread, allowing other threads to acquire the lock and therefore modify the object state. Upon waking, it reacquires the lock before returning. Intuitively, calling wait means “I want to go to sleep, but wake me when something interesting happens”, and calling the notification methods means “something interesting happened”.
https://www.liaoxuefeng.com/wiki/1252599548343744/1306580911915042
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
“`