在下面的代码中,我希望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);
}
这可以工作,但是执行繁忙的循环,而真实的信号量则不行,这就是为什么使用真实的信号量会更好的原因恕我直言