2016-06-02 17 views
1

Eine meiner Aufgaben in der Schule ist es, diesen Code zu reparieren. Der Erzeuger- und der Verbraucher-Thread sollten ihre lokale Variable abwechselnd erhöhen und ausdrucken, aber ich habe keine Ahnung, wie ich sie beheben kann.C: Produzent/Verbraucher

Es sollte möglich sein, dass der Produzent und Consumer-Thread das auf unbestimmte Zeit tun können, aber wenn ich die ausführbare Datei starte, stoppt es willkürlich.

Es wäre toll, wenn mir jemand dieses Verhalten erklären könnte. Hier

ist der Code:

#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; 
} 

Der Ausgang wie in diesem Beispiel aussehen:

$ ./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

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

+0

Hinweis: Warum muss der Consumer-Thread 'sleep (1)' bevor er zuerst den 'cond_consumed' CV signalisiert? –

+0

Tipp 2: Wo ist es möglich, dass jeder Thread blockiert wird? –

Antwort

3

Das Problem, das auftreten kann, ist, dass thread_A Signale vor thread_B die pthread_cond_wait Anweisung erreicht hat. Thread_B würde niemals das Signal sehen und stattdessen darauf warten.

Nach dem specs:

Die pthread_cond_signal() und pthread_cond_broadcast() Funktionen haben keine Wirkung, wenn es zur Zeit auf Ltg blockiert keine Themen sind.

Dies würde zu einem Deadlock führen, was Sie gerade erleben.

2

Ich habe Tour-Code ausgeführt. Dies führt zu einem Deadlock. Beide Threads warten auf die Zustandsvariable. Unten ist die gdb-Ablaufverfolgung.

(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 [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. 

Bitte verwenden Sie die Zustandsvariable richtig oder verwenden Sie Semaphor. Semaphore sind einfach in Konsumentenproblemen von Produzenten zu verwenden.