从这个信号量教程中提取说:
使用这样的信号量可以避免丢失信号。您将调用 take() 而不是 notify() 和 release() 而不是 wait()。如果对 take() 的调用发生在对 release() 的调用之前,调用 release() 的线程仍然会知道调用了 take(),因为信号内部存储在信号变量中。wait() 和 notify() 不是这种情况。
我们不能单独使用等待和通知来避免错过的信号吗?
从这个信号量教程中提取说:
使用这样的信号量可以避免丢失信号。您将调用 take() 而不是 notify() 和 release() 而不是 wait()。如果对 take() 的调用发生在对 release() 的调用之前,调用 release() 的线程仍然会知道调用了 take(),因为信号内部存储在信号变量中。wait() 和 notify() 不是这种情况。
我们不能单独使用等待和通知来避免错过的信号吗?
等待并通知您应该始终
注意:wait() 可能会虚假唤醒,因此您不能假设调用了 notify()。
我们不能单独使用等待和通知来避免错过的信号吗?
不,你永远不可能,这就是为什么它总是被认为与状态变化有关。
例如,一个常见的面试问题是编写一个简单的阻塞队列。
// a simple blocking queue using an AtomicReference
final Object lock = new Object();
final E eRef = null;
public void push(E e) {
synchronized(lock) {
while(eRef != null)
lock.wait();
eRef = e;
lock.notifyAll();
}
}
public E take() {
synchronized(lock) {
while(eRef == null)
lock.wait();
E e = eRef;
eRef = null;
lock.notifyAll();
return e;
}
}
当您有两个线程,其中一个在另一个调用notify()
之前调用时,可能会出现错过的信号wait()
。避免这种情况发生的唯一方法是设置某种屏障,使第二个线程等待第一个线程调用notify()
- 可用于创建此屏障的一种机制是信号量:)