バインダー付きプロデューサーの問題を解決するために、セマフォーを使用してCでモニターを実装しようとしました。 以下は私がモニターを実装するために使用したコードです。セマフォーを使用してCでモニターを実装すると、デッドロックにつながる
#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;
}
が、残念ながら、それはデッドロックにつながります。私はプロセスをチェックし、すべてのプロデューサーとコンシューマーがミューテックスを待つことを知りました。私は何をすべきか?
「producerCount」と「consumerCount」のどちらもゼロでないことは確かですか?あなたはデバッガでコードを踏んだことがありますか? – jwdonahue
私はそれが10人のプロデューサと10人のコンシューマを生成し、セマフォのミューテックスを解放するのを待っている間に、プログラムのある時点でそれらのすべてがブロックされていると確信しています。 – zari
値でセマフォを渡すことはできますか? –