0

我正在尝试使用信号量对生产者/消费者问题进行编码。我有 3 个,1 个用作互斥体,另外 2 个用作生产者和消费者可以添加/删除的缓冲区。从缓冲区添加/删除时,我使用二进制信号量来锁定/解锁它,这样全局变量就不会受到任何竞争条件的影响。生产信号量表示缓冲区中有多少可用点(可以将多少东西放入缓冲区),而消费者信号量表示可以从缓冲区中删除多少东西。我认为我的逻辑是错误的,因为我总是陷入僵局。此外,当我删除生产和消费信号量只是为了测试程序是否完成了它应该做的事情时,即使二进制信号量应该阻止它,我仍然会遇到竞争条件。我究竟做错了什么?

enter code here
#include <stdio.h>  
#include <sys/types.h>  
#include <unistd.h> 
#include <stdlib.h>     
#include <sys/wait.h>   
#include <pthread.h>
#include </usr/include/semaphore.h>

#define MAXITEMS 100    
#define PRODUCER_NO 5   
#define NUM_PRODUCED 5 

void *producer_function (void);
void *consumer_function (void);
void add_buffer (long i);
long get_buffer ();


long sum_value = 0; 
long finished_producers;
long buffer[MAXITEMS];  
int size = 0;       
int front, rear = 0;    

pthread_t producerThread[5];
pthread_t consumerThread;
sem_t mutex, produce, consume;

int main(void)
{
    int i = 0;
    srand (time(NULL));
    sem_init (&mutex, 0, 1);
    sem_init (&produce, 0, 100);
    sem_init (&consume, 0, 0);
    for (i = 0; i < 5; i++)
    {
        pthread_create (&producerThread[i], NULL, (void *) producer_function, NULL);
    }
    pthread_create (&consumerThread, NULL, (void *) consumer_function, NULL);
    for (i = 0; i < 5; i++)
    {
        pthread_join (producerThread[i], NULL);
    }
    pthread_join (consumerThread, NULL);
    return(0);
}

void *producer_function(void)
{   
    long counter = 0;
    long producer_sum = 0L;
    while (counter < NUM_PRODUCED) 
    {
        sem_wait (&mutex);
        sem_wait (&produce);
        long rndNum = rand() % 10; 
        producer_sum += rndNum;
        add_buffer (rndNum);
        sem_post (&consume);
        counter++;
        if (counter == NUM_PRODUCED)
        {
            finished_producers++;
        }
        sem_post (&mutex);
        usleep(1000);
    }

    printf("--+---+----+----------+---------+---+--+---+------+----\n");
    printf("The sum of produced items for this producer at the end is: %ld \n", producer_sum);
    printf("--+---+----+----------+---------+---+--+---+------+----\n");
    return(0);
}

void *consumer_function (void)
{   
    while (1) 
    {
        sem_wait (&mutex);
        sem_wait (&consume);
        long readnum = get_buffer();
        sem_post (&produce);
        sum_value += readnum;
        sem_post (&mutex);
        //printf ("%ld\n", sum_value);
        if ((finished_producers == PRODUCER_NO) && (size == 0))
        {
            printf("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n");
            printf("The sum of the all produced items at the end is: %ld \n", sum_value);
            printf("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n");
            break;
        }
    }
}

void add_buffer(long i){
    buffer[rear] = i;
    rear = (rear+1) % MAXITEMS;
    size++;
}

long get_buffer(){
    long v;
    v = buffer[front];
    front = (front+1) % MAXITEMS;
    size--;
    return v;
}
4

1 回答 1

0

用户2929779,

我认为在等待消费者中的消费通知时,不锁定互斥锁至关重要,反之亦然,生产者中的生产通知。想象一下,您因为等待消费通知而被阻止,并且没有生产者能够发布这样的通知,然后您的消费者保持互斥锁锁定,并且没有生产者有机会生产新项目......

所以这里的顺序很重要:1.)首先等待来自远程端的通知 2.)锁定互斥锁 3.)修改全局数据 4.)释放互斥锁 5.)通知远程端

试试这个:

void *producer_function(void)
{   
    long counter = 0;
    long producer_sum = 0L;
    while (counter < NUM_PRODUCED) 
    {

        sem_wait (&produce);
        sem_wait (&mutex);
        long rndNum = rand() % 10;
        producer_sum += rndNum;
        add_buffer (rndNum);
        counter++;
        if (counter == NUM_PRODUCED)
        {
            finished_producers++;
        }
        sem_post (&mutex);      
        sem_post (&consume);
        usleep(1000);
    }

    printf("--+---+----+----------+---------+---+--+---+------+----\n");
    printf("The sum of produced items for this producer at the end is: %ld \n", producer_sum);
    printf("--+---+----+----------+---------+---+--+---+------+----\n");
    return(0);
}

void *consumer_function (void)
{   
    while (1) 
    {

        sem_wait (&consume);
        sem_wait (&mutex);
        long readnum = get_buffer();
        sum_value += readnum;
        if ((finished_producers == PRODUCER_NO) && (size == 0))
        {
            printf("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n");
            printf("The sum of the all produced items at the end is: %ld \n", sum_value);
            printf("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n");
            break;
        }
        sem_post (&mutex);
        sem_post (&produce);

    //printf ("%ld\n", sum_value);
    }
    return(0);
}

PS 现在忽略系统调用的返回值只是为了展示示例实现......

PSS 另请参阅 wiki 上的伪代码http://en.wikipedia.org/wiki/Producer%E2%80%93consumer_problem#Using_semaphores ...

于 2013-10-28T23:19:47.863 回答