2016-10-26 14 views
1

아래의 소스 코드는 정확히 다음과 같이 작동합니다. 문제는 필자가 print f 문을 사용하여 코드가 "멈추는"위치를 찾았 기 때문에 만 작동하도록했습니다. 나는 내부 루프에서 뮤텍스가 잠금 기능을 사용하지 않고 잠겨 있어야하는 이유를 이해하지 못합니다. 미안하지만 그것이 분명하지는 않지만 직접 이해하는 데 문제가 있습니다.전역 변수에 액세스하려는 경우이 mutex가 "잠금"하지 않아야합니까?

정상적으로 문제의 코드 스 니프를 맨 위에 올리고 그 아래에 전체 소스 코드를 넣을 것입니다.

#include <stdio.h> 
#include <stdlib.h> 
#include <pthread.h> 

#define NITEMS 10    // number of items in shared buffer 

// shared variables 
char shared_buffer[NITEMS];  // echo buffer 
int shared_count;    // item count 

pthread_mutex_t mutex;   // pthread mutex 
pthread_cond_t bufferNotEmpty; // pthread condition variable for consumer thread 
pthread_cond_t bufferNotFull; // pthread condition variable for producer thread 

unsigned int prod_index = 0; // producer index into shared buffer 
unsigned int cons_index = 0; // consumer index into shared buffer 

// function prototypes 
void * producer(void *arg); 
void * consumer(void *arg); 

int main() 
{ 
    pthread_t prod_tid, cons_tid1, cons_tid2; 

    // initialize pthread variables 
    pthread_mutex_init(&mutex, NULL); 
    pthread_cond_init(&bufferNotEmpty, NULL); 
    pthread_cond_init(&bufferNotFull, NULL); 

    // start producer thread 
    pthread_create(&prod_tid, NULL, producer, NULL); 

    // start consumer threads 
    pthread_create(&cons_tid1, NULL, consumer, NULL); 
    pthread_create(&cons_tid2, NULL, consumer, NULL); 

    // wait for threads to finish 
    pthread_join(prod_tid, NULL); 
    pthread_join(cons_tid1, NULL); 
    pthread_join(cons_tid2, NULL); 

    // clean up 
    pthread_mutex_destroy(&mutex); 
    pthread_cond_destroy(&bufferNotEmpty); 
    pthread_cond_destroy(&bufferNotFull); 

    return 0; 
} 

// producer thread executes this function 
void * producer(void *arg) 
{ 
    char key; 

    while (1) 
    { 
     // read input key 
     scanf("%c", &key); 

     while (1) 
     { 
      // acquire mutex lock 
      pthread_mutex_lock(&mutex); 

      // if buffer is full, release mutex lock and check again 
      if (shared_count == NITEMS) 
      { 
       // Signal consumer thread and sleep 
       pthread_cond_signal(&bufferNotEmpty); 
       pthread_cond_wait(&bufferNotFull,&mutex); 
       pthread_mutex_unlock(&mutex); 
       break; 
      } 

      else 
       break; 
     } 

     // store key in shared buffer 
     shared_buffer[prod_index] = key; 

     // update shared count variable 
     shared_count++; 


     // update producer index 
     if (prod_index == NITEMS - 1) 
      prod_index = 0; 
     else 
      prod_index++; 

     // release mutex lock and signal consumer thread 
     pthread_mutex_unlock(&mutex); 
     pthread_cond_signal(&bufferNotEmpty); 
    } 

    return NULL; 
} 

// consumer thread executes this function 
void * consumer(void *arg) 
{ 
    char key; 

    int id = (int)pthread_self(); 

    while (1) 
    { 
     while (1) 
     { 
      // acquire mutex lock 
      pthread_mutex_lock(&mutex); 

      // if buffer is empty, wake producer thread and sleep 
      if (shared_count == 0) 
      { 
       pthread_cond_signal(&bufferNotFull); 
       pthread_cond_wait(&bufferNotEmpty,&mutex); 
       pthread_mutex_unlock(&mutex); 
      } 

      else 
       break; 
     } 

     // read key from shared buffer 
     key = shared_buffer[cons_index]; 

     // echo key 
     printf("consumer %d %c\n", id, key); 

     // update shared count variable 
     shared_count--; 

     // update consumer index 
     if (cons_index == NITEMS - 1) 
      cons_index = 0; 
     else 
      cons_index++; 

     // release mutex lock and signal producer thread 
     pthread_mutex_unlock(&mutex); 
     pthread_cond_signal(&bufferNotFull); 
    } 

    return NULL; 
} 

답변

5

당신은 대기 패턴이 잘못이 있습니다

  // if buffer is full, release mutex lock and check again 
     if (shared_count == NITEMS) 
     { 
      // Signal consumer thread and sleep 
      pthread_cond_signal(&bufferNotEmpty); 
      pthread_cond_wait(&bufferNotFull,&mutex); 
      pthread_mutex_unlock(&mutex); 
      break; 
     } 

다음은 전체 소스 코드입니다. 그것은 :

// acquire mutex lock 
    pthread_mutex_lock(&mutex); 

    // while buffer is empty, wait 
    while (shared_count == 0) 
    { 
     pthread_cond_wait(&bufferNotEmpty,&mutex); 
    } 

    // read key from shared buffer 
    key = shared_buffer[cons_index]; 

    // echo key 
    printf("consumer %d %c\n", id, key); 

    // update shared count variable 
    shared_count--; 

    // update consumer index 
    if (cons_index == NITEMS - 1) 
     cons_index = 0; 
    else 
     cons_index++; 

    // release mutex lock and signal producer thread 
    pthread_mutex_unlock(&mutex); 
    pthread_cond_signal(&bufferNotFull); 

같은 방법으로 반대편을 고칩니다. 조건이 충족 될 때까지 기다리는 루프가 필요하며 공유 상태가 엉망인 동안 (아마도 다시 획득 된) 뮤텍스를 보유하려고합니다.

알림 첫 번째 전화 번호는 pthread_cond_signal입니다. 인 경우 shared_count이 0이면 이미 다른 스레드를 깨 웠을 것입니다. 아직 아무것도 변경하지 않았으므로 아무에게도 말할 필요가 없습니다.

알림이 필요하지 않은 작업을 다른 스레드에 알리는 것은 의미가 없습니다. 기다리고있을 수있는 공유 상태를 변경했음을 다른 스레드에 알릴 필요가있을 때 pthread_cond_signal으로 전화하십시오.

성공적인 복귀시
+0

혼란 스럽습니다. 코드가 구현되는 방식이 이제는 잘 작동합니다. 그것이 효과가 없다고 말했거나, 당신이 제공 한 방식이 목표를 성취하는 더 좋은 방법 일뿐입니다. – Remixt

+0

@ Remixt 나는 함수를 올바르게 사용하는 방법에 대한 이해가 부족하다는 점을 반영하여 지나치게 복잡하게 작동한다고 말합니다. 그것은 부분적으로 행운을 빌며 가짜 웨이크 업을 제대로 처리하지 못하고 mutex를 두 번 연속해서 열 수 없기 때문에 운이 좋게 작동합니다. –

+0

설명해 주셔서 감사합니다. 감사합니다. – Remixt

2

, 뮤텍스는 잠겨 있어야한다 그래서

pthread_cond_wait(&bufferNotEmpty,&mutex); 
// mutex is already locked 
pthread_mutex_lock(&mutex); 
// deadlock 
를 호출 뮤텍스를 잠급니다 호출 스레드

https://linux.die.net/man/3/pthread_cond_wait

pthread_cond_wait() 소유 한다

교착 상태가 발생합니다.

+1

설명 주셔서 감사합니다! – Remixt