使用 pthreads 理解信号量(包含代码)

Understanding semaphores with pthreads (code included)

所以在 class 中,我们学习了信号量和其他东西,我们的教授让我们知道下面的这段代码对于我们的考试来说会很方便。不幸的是,我们的考试是在星期五,整个借口列表,我只需要能够理解这段代码以用于考试和未来的案例。我知道 mutex_t 是一个锁系统,cond_t 是一个条件系统,其中信号通过 sema_P 和 sema_V 传递(如果值为 0,竞争条件发生并且线程被 cond_wait 锁定,直到另一个线程增加值并被 cond_signal 解锁),但是为什么需要传递锁?为什么递减器P()和递增器V()中都有mutex_lock和mutex_unlock?这如何与线程和条件 (cont_t) 一起工作?

typedef struct
{
        pthread_mutex_t lock;
        pthread_cond_t wait;
        int value;
} sema;

void pthread_sema_init(sema *s, int count)
{
        s->value = count;
        pthread_cond_init(&(s->wait),NULL);
        pthread_mutex_init(&(s->lock),NULL);
        return;
}

void pthread_sema_P(sema *s)
{
        pthread_mutex_lock(&(s->lock));
        s->value--;
        if(s->value < 0) {
                pthread_cond_wait(&(s->wait),&(s->lock));
        }
        pthread_mutex_unlock(&(s->lock));
        return;
}

void pthread_sema_V(sema *s)
{

        pthread_mutex_lock(&(s->lock));
        s->value++;
        if(s->value <= 0) {
                pthread_cond_signal(&(s->wait));
        }
        pthread_mutex_unlock(&(s->lock));
}

互斥锁 sema.lock 用于保护共享变量 sema.value,确保一次只有一个线程访问该值。 pthread_sema_P()pthread_sema_V() 都必须获取锁,因为它们都访问 sema.value.

信号量的实现是错误的,顺便说一下 - 它不处理虚假唤醒("spurious wakeup" 是 pthread_cond_wait() 唤醒的地方,尽管没有收到信号 - 这是规范允许的).

更传统的实施方式可能是:

void pthread_sema_P(sema *s)
{
        pthread_mutex_lock(&s->lock);
        while (s->value < 1) {
                pthread_cond_wait(&s->wait, &s->lock);
        }
        s->value--;
        pthread_mutex_unlock(&s->lock);
}

void pthread_sema_V(sema *s)
{
        pthread_mutex_lock(&s->lock);
        s->value++;
        pthread_cond_signal(&s->wait);
        pthread_mutex_unlock(&s->lock);
}