C语言中的信号量和死锁

时间:2013-10-28 21:28:56

标签: c

我正在尝试使用信号量编码生产者/消费者问题。我有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;
}

1 个答案:

答案 0 :(得分:0)

user2929779,

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

所以顺序在这里很重要: 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);
}

P.S。现在忽略系统调用的返回值只是为了显示示例实现...

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