2017-10-24 7 views
2

バインダー付きプロデューサーの問題を解決するために、セマフォーを使用して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; 
} 

が、残念ながら、それはデッドロックにつながります。私はプロセスをチェックし、すべてのプロデューサーとコンシューマーがミューテックスを待つことを知りました。私は何をすべきか?

+0

「producerCount」と「consumerCount」のどちらもゼロでないことは確かですか?あなたはデバッガでコードを踏んだことがありますか? – jwdonahue

+0

私はそれが10人のプロデューサと10人のコンシューマを生成し、セマフォのミューテックスを解放するのを待っている間に、プログラムのある時点でそれらのすべてがブロックされていると確信しています。 – zari

+0

値でセマフォを渡すことはできますか? –

答えて

0

sem_post(&mutex);をあなたのinstertの最後に追加し、機能を削除してください。それぞれコールのほうがsem_postよりも多い1つの経路があります。

編集:このバグを修正しても、まだ設計上の欠陥があります。構造体に保護する必要がある各変数を配置し、その中にmutexを追加してから、それらの変数を読み書きする前にそのロックを取得して、すぐにロックを解放することをお勧めします。これは、1つのロックのアプローチの下にある、または全くありません。

+0

私はそうしましたが、バッファへの一貫性のないアクセスが発生しました。 – zari

+0

これは別のバグです。あなたはもうデッドロックに巻き込まれていません。 – jwdonahue

+0

それで、モニターが共有データへの一貫性のないアクセスにつながるモニターを使用する点は何ですか?私たちはモニターがそのような一貫性のないデータアクセスを防止するためのメカニズムであることを知っていますか? – zari

関連する問題