2016-06-02 19 views
1

学校での私の仕事の1つは、このコードを修正することです。プロデューサとコンシューマスレッドは、ローカル変数を交互にインクリメントして出力する必要がありますが、どのように修正するかわかりません。C:プロデューサー/コンシューマー

プロデューサとコンシューマのスレッドが無期限に実行できる可能性がありますが、実行可能ファイルを開始すると、任意に停止します。

誰かがこの行動を私に説明できるのは素晴らしいことです。ここで

コードは次のとおりです。

#include <sys/types.h> 
#include <stdio.h> 
#include <unistd.h> 
#include <pthread.h> 

static pthread_mutex_t mutex; 
static pthread_cond_t cond_consumed = PTHREAD_COND_INITIALIZER; 
static pthread_cond_t cond_produced = PTHREAD_COND_INITIALIZER; 

static void *producer(void *arg) 
{ 
     unsigned long count=0; 

     while(1) { 
       printf("producer: wait...\n"); 
       pthread_mutex_lock(&mutex); // enter critical section 
       pthread_cond_wait(&cond_consumed, &mutex); 
       printf("producer: PRODUCE %ld...\n", count++); 
       pthread_cond_signal(&cond_produced); 
       pthread_mutex_unlock(&mutex); // leave critical section 
     } 
     return NULL; 
} 

static void *consumer(void *arg) 
{ 
     unsigned long count=0; 

     sleep(1); 
     pthread_cond_signal(&cond_consumed); 
     while(1) { 
       printf("consumer: wait...\n"); 
       pthread_mutex_lock(&mutex); 
       pthread_cond_wait(&cond_produced, &mutex); 
       printf("consumer: CONSUME %ld...\n", count++); 
       pthread_cond_signal(&cond_consumed); 
       pthread_mutex_unlock(&mutex); 
     } 
     return NULL; 
} 

int main(int argc, char **argv, char **envp) 
{ 
     pthread_t p1, p2; 

     if (pthread_mutex_init(&mutex, NULL)) { 
       perror("pthread_mutex_init"); 
       return -1; 
     } 

     pthread_create(&p2, NULL, consumer, NULL); 
     pthread_create(&p1, NULL, producer, NULL); 

     pthread_join(p1, NULL); 
     pthread_join(p2, NULL); 

     pthread_mutex_destroy(&mutex); 
     return 0; 
} 

出力は、この例のようになります。発生する可能性があります

$ ./event 
producer: wait... 
consumer: wait... 
producer: PRODUCE 0... 
producer: wait... 
consumer: CONSUME 0... 
consumer: wait... 
producer: PRODUCE 1... 
producer: wait... 
consumer: CONSUME 1... 
consumer: wait... 
producer: PRODUCE 2... 
producer: wait... 
consumer: CONSUME 2... 
consumer: wait... 
.... 
+0

[こちら](https://stackoverflow.com/questions/29455170/c-threads-to-print-sequence-of-numbers-with-even-and-odd-number-printing-threa/29455846#) 29455846) – user3386109

+0

ヒント:コンシューマスレッドは、最初に 'cond_consumed' CVを通知する前に' sleep(1) 'する必要がありますか? –

+0

ヒント2:各スレッドをブロックすることは可能ですか? –

答えて

3

問題がthread_B前thread_A信号がpthread_cond_wait声明に達していることです。 Thread_Bはシグナルを見ず、代わりにそれを待っています。 specsによれば

:現在CONDでブロックされないスレッドが存在しない場合

pthread_cond_signalを()とpthread_cond_broadcastの()関数は影響を及ぼしません。

これは、発生しているデッドロックにつながります。

2

ツアーコードを実行しました。デッドロックが発生しています。 両方のスレッドが条件変数を待機しています。 以下はgdbトレースです。

(gdb) bt 
#0 0x00000032b2e0822d in pthread_join() from /lib64/libpthread.so.0 
#1 0x0000000000400a1c in main() 
(gdb) info thread 
3 Thread 0x7f78bfdb4700 (LWP 8125) 0x00000032b2e0b5bc in [email protected]@GLIBC_2.3.2() from /lib64/libpthread.so.0 
2 Thread 0x7f78bf3b3700 (LWP 8126) 0x00000032b2e0b5bc in pthread_co[email protected]@GLIBC_2.3.2() from /lib64/libpthread.so.0 
* 1 Thread 0x7f78bfdb6700 (LWP 8124) 0x00000032b2e0822d in pthread_join() from /lib64/libpthread.so.0 
(gdb) thread 2 
[Switching to thread 2 (Thread 0x7f78bf3b3700 (LWP 8126))]#0 0x00000032b2e0b5bc in [email protected]@GLIBC_2.3.2() 
from /lib64/libpthread.so.0 
(gdb) bt 
#0 0x00000032b2e0b5bc in [email protected]@GLIBC_2.3.2() from /lib64/libpthread.so.0 
#1 0x00000000004008eb in producer() 
#2 0x00000032b2e079d1 in start_thread() from /lib64/libpthread.so.0 
#3 0x00000032b26e8b6d in clone() from /lib64/libc.so.6 
(gdb) thread 2 
[Switching to thread 2 (Thread 0x7f78bf3b3700 (LWP 8126))]#0 0x00000032b2e0b5bc in [email protected]@GLIBC_2.3.2() 
from /lib64/libpthread.so.0 
(gdb) bt 
#0 0x00000032b2e0b5bc in [email protected]@GLIBC_2.3.2() from /lib64/libpthread.so.0 
#1 0x00000000004008eb in producer() 
#2 0x00000032b2e079d1 in start_thread() from /lib64/libpthread.so.0 
#3 0x00000032b26e8b6d in clone() from /lib64/libc.so.6 
gdb) thread 3 
[Switching to thread 3 (Thread 0x7f78bfdb4700 (LWP 8125))]#0 0x00000032b2e0b5bc in [email protected]@GLIBC_2.3.2() 
from /lib64/libpthread.so.0 
(gdb) bt 
#0 0x00000032b2e0b5bc in [email protected]@GLIBC_2.3.2() from /lib64/libpthread.so.0 
#1 0x000000000040096a in consumer() 
#2 0x00000032b2e079d1 in start_thread() from /lib64/libpthread.so.0 
#3 0x00000032b26e8b6d in clone() from /lib64/libc.so.6 

O/P: 
[email protected]:myExperiments$ ./a.out 
producer: wait... 
consumer: wait... 
producer: PRODUCE 0... 
producer: wait... 
consumer: CONSUME 0... 
consumer: wait... 
producer: PRODUCE 1... 
producer: wait... 
consumer: CONSUME 1... 
consumer: wait... 
Blocked after this. 

条件変数を正しく使用するか、セマフォを使用してください。セマフォは、プロデューサのコンシューマの問題で使用するのが簡単です。