在下面的代码中,我希望print语句将始终打印s=0(因为它是二进制信号量,并且已获取了锁)。

/// Producer Consumer problem using semaphores

#include<stdio.h>
#include<pthread.h>
#include<unistd.h>
#include<stdlib.h>

#define BUFF_SIZ 10

int s = 1; /// binary semaphore
int full = 0;
int empt = BUFF_SIZ;

int arr[BUFF_SIZ];
int value = 100;

void wait(int *s)
{
    while(*s <= 0);
    *s = *s - 1;
}
void signal(int* s)
{
    *s = *s + 1;
}
void *producer(void* param)
{
    for(int i=0;i<BUFF_SIZ;i++)
    {
        int new_item = value;
        value++;
        wait(&empt);
        wait(&s);

        printf("s = %d\n",s);
        printf("Producer inside critical section\n");
        printf("Produced item = %d\n\n",new_item);
        arr[i] = new_item;

        signal(&s);
        signal(&full);
    }
    pthread_exit(0);
}
void *consumer(void* param)
{
    for(int i=0;i<BUFF_SIZ;i++)
    {
        wait(&full);
        wait(&s);

        printf("s = %d\n",s);
        printf("Consumer inside critical section\n");
        printf("Consumed item = %d\n\n", arr[i]);

        signal(&s);
        signal(&empt);
    }
    pthread_exit(0);
}
int main()
{
    pthread_t tid_p,tid_c;
    pthread_attr_t attr1,attr2;
    pthread_attr_init(&attr1);
    pthread_attr_init(&attr2);

    pthread_create(&tid_p,&attr1,producer,NULL);
    pthread_create(&tid_c,&attr2,consumer,NULL);

    pthread_join(tid_p,NULL);
    pthread_join(tid_c,NULL);
    return 0;
}


但是输出是

s = 0
Producer inside critical section
Produced item = 100

s = 0
Producer inside critical section
Produced item = 101

s = 0
Producer inside critical section
Produced item = 102

s = -1
Consumer inside critical section
Consumed item = 100

s = 0
Producer inside critical section
Produced item = 103

s = 0
Producer inside critical section
Produced item = 104

s = -1
Consumer inside critical section
Consumed item = 101

s = 0
Consumer inside critical section
Consumed item = 102

s = 0
Consumer inside critical section
Consumed item = 103

s = 0
Consumer inside critical section
Consumed item = 104

s = -1
Producer inside critical section
Produced item = 105

s = 0
Producer inside critical section
Produced item = 106

s = 0
Producer inside critical section
Produced item = 107

s = -1
Consumer inside critical section
Consumed item = 105

s = 0
Consumer inside critical section
Consumed item = 106

s = 0
s = 0
Producer inside critical section
Produced item = 108

s = 0
Producer inside critical section
Produced item = 109

Consumer inside critical section
Consumed item = 107

s = 1
Consumer inside critical section
Consumed item = 108

s = 1
Consumer inside critical section
Consumed item = 109


因此,根据我的说法,这是由于wait()函数的非原子操作引起的竞争状态(让我知道我是否做错了)。有什么办法可以避免这种情况?

最佳答案

您可以尝试用一些伪信号量替换s,full,empt整数:

struct pseudo_sem {
    int value; /// binary semaphore
    pthread_mutex_t mutex;
};
struct pseudo_sem s = { 1, PTHREAD_MUTEX_INITIALIZER };
struct pseudo_sem full = { 0, PTHREAD_MUTEX_INITIALIZER };
struct pseudo_sem empt = { BUFF_SIZ, PTHREAD_MUTEX_INITIALIZER };

void wait(struct pseudo_sem *s)
{
    pthread_mutex_lock(&s->mutex);
    while(s->value <= 0) {
        pthread_mutex_unlock(&s->mutex);
        usleep(100); // be kind, sleep a bit
        pthread_mutex_lock(&s->mutex);
    }
    s->value--;
    pthread_mutex_unlock(&s->mutex);
}

void signal(struct pseudo_sem* s)
{
    pthread_mutex_lock(&s->mutex);
    s->value++;
    pthread_mutex_unlock(&s->mutex);
}


这可以工作,但是执行繁忙的循环,而真实的信号量则不行,这就是为什么使用真实的信号量会更好的原因恕我直言

08-16 07:54