且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

这是如何实现的信号灯工作?

更新时间: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 the sem_wait() function.

The pthread_cond_signal() function call that cond_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 variable cond (if any threads are blocked on cond).

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. The wakeups counter ensures that only the appropriate number of threads actually make it out of the sem_wait() function. The other ones will remain in the do/while loop and wait on the condition again.