为什么使用 notify 和 notifyAll 的时候要先获得锁?
1
cs419 2020-05-30 17:19:43 +08:00
没这个说法 不搭嘎
你想想 1. 为啥要用锁,不用锁会出啥问题 (原子性) 2. 面对这个问题 怎么用 notify 去解决 (线程等待) 如果确实要线程等待 一般不用 notify 用 LockSupport |
2
linxiaoziruo OP @cs419 怎么会不搭嘎呢,使用 notify 和 notifyAll 的时候必须要在 syncnorize 的临界区内,即必须先获得这个对象锁才能执行 notify,否则会抛出 IllegalMonitorStateException
|
3
linxiaoziruo OP @cs419 锁是解决共享资源竞争引起的线程安全问题,和原子性有什么关联呢,原子性指的是不能中断的操作,和锁是两个没有关联的概念。
|
4
23571113 2020-05-30 20:25:49 +08:00
notify 就是通知释放锁啊, 你没锁怎么释放.
|
5
pursuer 2020-05-30 20:27:30 +08:00
notify,wait,和条件判断通常是一起用的,条件判断后选择进入等待或继续运行,这个时候要保证条件判断后,条件不会被其他线程改变,所以通常都会有个锁保障类似的场景。
|
6
sioncheng 2020-05-30 21:50:39 +08:00
notify \ wait 是一种协作吧,双方需要能获得相同的锁才能说明是是在协作干一个事情,要不然,不相干的参与者瞎 notify 能行吗
|
7
lux182 2020-05-30 23:57:01 +08:00
释放 monitor
唤醒等待队列的线程 |
8
seki4713 2020-05-31 14:23:47 +08:00 via iPhone
防止你条件判断成功后突然被抢占 然后条件被修改 保证判断条件到进入临界区的整个操作是原子的
|
9
bigbyto 2020-05-31 20:48:34 +08:00
这个问题其实真不好回答,就像大家习以为常的问题,突然被问为什么了。其实上面的老哥都没回答到点上,我觉得为什么 notify 必须要 synchorized,根本原因在于 wait set 的操作是原子的。先看看 JLS 对 wait set 的描述。
> 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 的操作是原子的。 |
10
JasonLaw 2020-06-01 08:19:03 +08:00 via iPhone
来自 Java Concurrency in Practice 。
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”. |
11
willxiang 2020-06-01 09:14:46 +08:00
"必须在 synchronized 块中才能调用 wait()方法,因为 wait()方法调用时,会释放线程获得的锁,wait()方法返回后,线程又会重新试图获得锁。"
https://www.liaoxuefeng.com/wiki/1252599548343744/1306580911915042 |
12
cs419 2020-06-01 10:28:56 +08:00
忽然发现被降权了 没收到消息通知
奇怪的知识增加了 没觉着 wait 好用 平时要么普通的多线程 要么 LockSupport 要么 JUC |
13
Kamiyu0087 2020-06-01 11:33:58 +08:00
直接从实际使用的情况来看的话,你如果 notify 的时候不去获得锁的话,没法保证 notify 在 wait 之后再执行啊
```java final Object lock = new Object(); synchronized (lock) { new Thread(() -> lock.notify()).start(); try { lock.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } ``` |