这种信号量的实现如何工作?

圣诞快乐!

我正在读“信号量小书” 。 书中有一个C语言的实现,我并不完全理解。 请参阅下面的代码。 有这个唤醒变量。 作者解释说:

唤醒计算未决信号的数量; 也就是说,已被唤醒但尚未恢复执行的线程数。 唤醒的原因是为了确保我们的信号量具有第4.3节中描述的属性3

属性3:如果线程执行信号时有线程在等待信号量,则必须唤醒其中一个等待线程。

好的,我想我理解了这个属性的含义。 其中一个等待线程应该获取互斥锁而不是另一个(例如信令线程)。如果我错了,请纠正我。 我不明白的是这个机制如何保证这个属性。 我会说房产不保证。 非等待进程仍然可能获得互斥锁。 我错过了什么?

typedef struct { int value, wakeups; Mutex *mutex; Cond *cond; } Semaphore; // SEMAPHORE Semaphore *make_semaphore (int value) { Semaphore *semaphore = check_malloc (sizeof(Semaphore)); semaphore->value = value; semaphore->wakeups = 0; semaphore->mutex = make_mutex (); semaphore->cond = make_cond (); return semaphore; } void sem_wait (Semaphore *semaphore) { mutex_lock (semaphore->mutex); semaphore->value--; if (semaphore->value cond, semaphore->mutex); } while (semaphore->wakeups wakeups--; } mutex_unlock (semaphore->mutex); } void sem_signal (Semaphore *semaphore) { mutex_lock (semaphore->mutex); semaphore->value++; if (semaphore->value wakeups++; cond_signal (semaphore->cond); } mutex_unlock (semaphore->mutex); } 

wakeups成员不是为了保护互斥锁不被等待线程以外的东西获取 – 它旨在防止从sem_wait()函数中释放太multithreading。

cond_signal()包装的pthread_cond_signal()函数调用在其文档中具有以下语句(重点已添加):

pthread_cond_signal()函数应解除阻塞在指定条件变量cond上阻塞的至少一个线程(如果在cond上阻塞了任何线程)。

和:

在多处理器上, pthread_cond_signal()的实现可能无法避免在条件变量上阻塞多个线程。

举例来说,当3个线程在条件上等待时,可能会在进行cond_signal()调用时释放两个(或全部三个)。 wakeups计数器确保只有适当数量的线程实际上使它脱离sem_wait()函数。 其他的将保留在do / while循环中并再次等待条件。

这个属性意味着信令线程应该代表其中一个等待线程释放CPU,如果有的话。 pthread_cond_signal()完全保证了这个原因并且出于同样的原因。

pthread_cond_signal()函数应解除阻塞在指定条件变量cond上阻塞的至少一个线程(如果在cond上阻塞了任何线程)。