更新时间:2023-02-26 17:56:18
的唤醒
成员是不是为了保护互斥从不是等待线程以外的东西被收购 - 这是旨在prevent过多的线程从 sem_wait()
函数释放
的调用pthread_cond_signal()
函数调用 cond_signal()
包装具有以下语句的 nofollow的>(强调):
的
调用pthread_cond_signal()
功能应被阻止在指定条件变量的线程解锁的至少一个COND
(如果有的话线程被阻塞在COND
)。
块引用>和
在多处理器,它可以对一个实现是不可能的
调用pthread_cond_signal()
,以避免阻塞条件变量多个线程的疏导。
块引用>因此,作为一个例子,这是可能的,当3线程对条件等待,即两个(或全部三个)可能被当
cond_signal()
呼叫释放制作。在唤醒
计数器确保只有线程适当数量居然能走出sem_wait()
的功能。其他的人将继续留在不要
/,而
循环并且再次等待条件。Merry Xmas!
I'm reading the The Little Book of Semaphores. There is an implementation of semaphores in C in the book that I don't completely understand. See below for code. There is this wakeups variable. The author explains:
wakeups counts the number of pending signals; that is, the number of threads that have been woken but have not yet resumed execution. The reason for wakeups is to make sure that our semaphores have Property 3, described in Section 4.3
and
Property 3: if there are threads waiting on a semaphore when a thread executes signal, then one of the waiting threads has to be woken.
Ok, I think I understand the meaning of the property. One of the waiting threads should get the mutex and not another one (for example the signaling threads.) Correct me if I'm wrong. What I do not understand is how this property is guaranteed with this mechanism. I'd say the property is not guaranteed. It's still possible that a non-waiting process gets the mutex. What am I missing?
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 < 0) { do { cond_wait (semaphore->cond, semaphore->mutex); } while (semaphore->wakeups < 1); semaphore->wakeups--; } mutex_unlock (semaphore->mutex); } void sem_signal (Semaphore *semaphore) { mutex_lock (semaphore->mutex); semaphore->value++; if (semaphore->value <= 0) { semaphore->wakeups++; cond_signal (semaphore->cond); } mutex_unlock (semaphore->mutex); }
The
wakeups
member is not intended to protect the mutex from being acquired by something other than a waiting thread - it's intended to prevent too many threads from being released from thesem_wait()
function.The
pthread_cond_signal()
function call thatcond_signal()
wraps has the following statements in its documentation (emphasis added):The
pthread_cond_signal()
function shall unblock at least one of the threads that are blocked on the specified condition variablecond
(if any threads are blocked oncond
).And:
On a multi-processor, it may be impossible for an implementation of
pthread_cond_signal()
to avoid the unblocking of more than one thread blocked on a condition variable.So as an example, it's possible that when 3 threads are waiting on the condition, that two (or all three) might be released when the
cond_signal()
call is made. Thewakeups
counter ensures that only the appropriate number of threads actually make it out of thesem_wait()
function. The other ones will remain in thedo
/while
loop and wait on the condition again.