我尝试使用信号量在C中实现monitor,以便用有界缓冲区解决生产者消费者问题。 以下是我用来实现监视器的代码。
#include<semaphore.h>
int availableItemCounts;
int bufferSize;
int itemShouldBeProducedCount;
int itemShouldBeConsumedCount;
int availableItemIndex;//index of last item inserted in buffer.
char *buffer;
sem_t mutex;
typedef struct
{
sem_t semaphore;
int numberOfBlockedThreads;
} Condition;
Condition bufferIsFull, bufferIsEmpty;
int countCV(Condition conditionVariable)
{
return conditionVariable.numberOfBlockedThreads;
}
void waitCV(Condition conditionVariable)
{
conditionVariable.numberOfBlockedThreads++;
sem_wait(&(conditionVariable.semaphore));
}
void signalCV(Condition conditionVariable)
{
if(countCV(conditionVariable)>0)
{
sem_post(&(conditionVariable.semaphore));
conditionVariable.numberOfBlockedThreads--;
}
else
{
sem_post(&mutex);
}
}
void monitorInit(int buffSize, int itemSBPC,int itemSBCC)
{
availableItemCounts=0;
availableItemIndex=-1;
bufferSize=buffSize;
itemShouldBeProducedCount=itemSBPC;
itemShouldBeConsumedCount=itemSBCC;
char tempBuffer[bufferSize];
buffer=tempBuffer;
sem_init(&(bufferIsFull.semaphore), 0, 0);
sem_init(&(bufferIsEmpty.semaphore), 0, 0);
sem_init(&(mutex), 0, 1);
bufferIsEmpty.numberOfBlockedThreads=0;
bufferIsFull.numberOfBlockedThreads=0;
}
void monitor_Insert(char item)
{
sem_wait(&mutex);
if (itemShouldBeProducedCount>0)
{
if(availableItemCounts==bufferSize)
{
sem_post(&mutex);
waitCV(bufferIsFull);
sem_wait(&mutex);
}
availableItemIndex++;
buffer[availableItemIndex]=item;
printf("p:%lu, item: %c, at %d\n", pthread_self(), item, availableItemIndex);
itemShouldBeProducedCount--;
availableItemCounts++;
signalCV(bufferIsEmpty);
}
else
{
sem_post(&mutex);
pthread_exit(NULL);
}
}
void monitor_Remove(char item)
{
sem_wait(&mutex);
if (itemShouldBeConsumedCount>0)
{
if(availableItemCounts==0)
{
sem_post(&mutex);
waitCV(bufferIsEmpty);
sem_wait(&mutex);
}
item=buffer[availableItemIndex];
printf("c:%lu, item: %c, at %d\n", pthread_self(), item, availableItemIndex);
availableItemIndex--;
itemShouldBeConsumedCount--;
availableItemCounts--;
signalCV(bufferIsFull);
}
else
{
sem_post(&mutex);
pthread_exit(NULL);
}
}
这是我的主文件(主要功能):
#include<stdio.h>
#include<pthread.h>
#include<semaphore.h>
#include<stdlib.h>
#include "Monitor.h"
void *produce(void *index);
void *consume(void *index);
int itemShouldBeProducedCount;//total number of items that should be produced.
int itemShouldBeConsumedCount;//total number of items that should be consumed.
int bufferSize;
int main(int argc, char **argv)
{
int index;
int error;
int producerCount=atoi( argv[4]);
int consumerCount=atoi( argv[6]);
itemShouldBeProducedCount=atoi( argv[8]);
itemShouldBeConsumedCount=itemShouldBeProducedCount;
bufferSize=atoi( argv[2]);
monitorInit(bufferSize,itemShouldBeProducedCount,itemShouldBeConsumedCount);
sem_init(&(bufferIsFull.semaphore), 0, 0);
sem_init(&(bufferIsEmpty.semaphore), 0, 0);
printf("Producer Count:%d\n", producerCount);
printf("Consumer Count:%d\n", consumerCount);
printf("Buffer size Count:%d\n", bufferSize);
printf("Items should be produced:%d\n", itemShouldBeProducedCount);
printf("Items should be consumed:%d\n", itemShouldBeConsumedCount);
monitorInit(bufferSize,itemShouldBeProducedCount,itemShouldBeConsumedCount);
pthread_t producerThreads[ producerCount ];
pthread_t consumerThreads[ consumerCount ];
for( index = 0; index < producerCount; index++ )
{
printf("In main: creating producer thread %d\n", index);
error = pthread_create( &producerThreads[index], NULL, produce, &index );
}
for( index = 0; index < consumerCount; index++ )
{
printf("In main: creating consumer thread %d\n", index);
error = pthread_create( &consumerThreads[index], NULL, consume, &index );
}
// wait for each producer thread to complete
for( index = 0; index < producerCount; ++index )
{
// block until thread 'index' completes
pthread_join( producerThreads[ index ], NULL );
printf( "In main: producer thread %d has completed\n", index );
}
// wait for each consumer thread to complete
for( index = 0; index < consumerCount; ++index )
{
// block until thread 'index' completes
pthread_join( consumerThreads[ index ], NULL );
printf( "In main: consumer thread %d has completed\n", index );
}
sem_destroy(&(bufferIsFull.semaphore));
sem_destroy(&(bufferIsEmpty.semaphore));
return 0;
}
void *produce(void *threaID)
{
unsigned char item;
while(1)
{
item= (unsigned char) (rand() % 256);//generating an item
monitor_Insert(item);
}
return NULL;
}
void *consume(void *threaID)
{
while(1)
{
char item;
monitor_Remove(item);
}
return NULL;
}
但不幸的是它会导致死锁。我检查了进程,发现所有生产者和消费者都在等待互斥锁。我该怎么办?
答案 0 :(得分:0)
将sem_post(&mutex);
添加到您的instert的末尾并删除功能。每个通道都有一条途径可以导致sem_wait
次呼叫比sem_post
更多。