2017-10-24 27 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 '가 0이 아닌 것은 확실합니까? 디버거로 코드를 밟았습니까? – jwdonahue

+0

나는 10 명의 생산자와 10 명의 소비자를 생성하고, 프로그램의 어느 시점에서 이들 모두가 차단되었다고 확신하며, 그들은 세마포어 뮤텍스를 공개하기를 기다리고있다. – zari

+0

값으로 세마포를 통과 할 수 있습니까? –

답변

0

sem_post(&mutex);을 instert의 끝에 추가하고 기능을 제거하십시오. 각각 번의 전화가 sem_post이 넘는 경로가 있습니다.

편집 :이 버그를 수정 한 후에도 여전히 설계상의 결함이 있습니다. 구조체에 보호해야하는 각 변수를 배치하고 그 중 하나에 뮤텍스를 추가 한 다음 해당 변수를 읽고 쓰기 전에 해당 잠금을 획득하고 완료되면 잠금을 해제하는 것이 좋습니다. 이것은 하나의 잠금 접근법의 전부 또는 일부입니다.

+0

나는 그렇게했지만 버퍼에 대한 일관성없는 액세스가 발생했습니다. – zari

+0

다른 버그입니다. 너는 더 이상 교착 상태에 빠지지 않았다. – jwdonahue

+0

그럼 모니터가 공유 데이터에 대한 일관성없는 액세스를 유발하는 모니터를 사용하는 시점은 무엇입니까? 우리는 모니터가 일관성없는 데이터 액세스를 방지하는 데 사용되는 메커니즘이라는 것을 알고 있습니까? – zari