2

从这个信号量教程中提取说:

使用这样的信号量可以避免丢失信号。您将调用 take() 而不是 notify() 和 release() 而不是 wait()。如果对 take() 的调用发生在对 release() 的调用之前,调用 release() 的线程仍然会知道调用了 take(),因为信号内部存储在信号变量中。wait() 和 notify() 不是这种情况。

我们不能单独使用等待和通知来避免错过的信号吗?

4

2 回答 2

3

等待并通知您应该始终

  • 根据条件等待
  • 通知哪个更改了等待检查的状态。

注意: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;
    }
}
于 2013-06-10T20:27:51.920 回答
3

当您有两个线程,其中一个在另一个调用notify()之前调用时,可能会出现错过的信号wait()。避免这种情况发生的唯一方法是设置某种屏障,使第二个线程等待第一个线程调用notify()- 可用于创建此屏障的一种机制是信号量:)

于 2013-06-10T20:30:29.323 回答