【问题标题】:How does this implementation of semaphore work?这种信号量的实现是如何工作的?
【发布时间】:2011-05-30 09:32:16
【问题描述】:

圣诞快乐!

我正在阅读The Little Book of Semaphores。书中有一个用 C 语言实现的信号量,我并不完全理解。请参阅下面的代码。有这个 wakeups 变量。作者解释:

wakeups 计算待处理信号的数量;即已被唤醒但尚未恢复执行的线程数。唤醒的原因是确保我们的信号量具有属性 3,如第 4.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 < 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);
}

【问题讨论】:

    标签: c multithreading mutex semaphore conditional-statements


    【解决方案1】:

    wakeups 成员并非旨在保护互斥锁不被等待线程以外的其他对象获取 - 它旨在防止从sem_wait() 函数中释放过多线程。

    cond_signal() 包装的pthread_cond_signal() 函数调用具有以下语句in its documentation(已添加重点):

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

    还有:

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

    因此,例如,当 3 个线程正在等待条件时,可能会在调用 cond_signal() 时释放其中两个(或全部三个)。 wakeups 计数器确保只有适当数量的线程才能真正退出sem_wait() 函数。其他的将保留在do/while 循环中并再次等待条件。

    【讨论】:

      【解决方案2】:

      这个属性的意思是信号线程应该代表一个等待线程释放CPU,如果有的话。 pthread_cond_signal() 正是出于同样的原因保证了这一点。

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

      【讨论】:

      • 好的,唤醒在这里有什么帮助?唤醒如何帮助保证此属性?
      • 这个属性由 cond_signal() 保证,一些等待的线程将被恢复。 this->wakeups 只是有助于计算其中有多少实际上可以继续执行。不能依赖 this->value 因为它可能是负数,所以需要单独的变量。
      • 对不起,我对这个解释不太满意。我了解 phtread_cond_signal 的作用,但据我了解作者,这并不能保证该属性。第一句话的第二句话怎么样? “wakeups 的原因是为了确保我们的信号量具有属性 3,在第 4.3 节中进行了描述”作者在这里不是明确地说wakeups 保证了该属性吗?
      猜你喜欢
      • 2014-12-18
      • 2016-05-14
      • 2016-02-10
      • 1970-01-01
      • 2019-10-29
      • 2010-11-16
      • 2020-03-13
      • 2011-12-15
      • 1970-01-01
      相关资源
      最近更新 更多