user6275750
user6275750

Reputation:

C: Producer / Consumer

One of my task at the school is to fix this code. The producer and consumer thread should alternatly increment their local variable and print it out, but i have no idea how to fix it.

It should be possible that the producer and consumer thread can do that indefinitely, but if I start the executable it stops arbitrarily.

It would be great if someone could explain me this behavior.

Here is the 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;
}

The output should look like this example:

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

Upvotes: 1

Views: 1143

Answers (2)

sagar
sagar

Reputation: 387

I have executed tour code. It is resulting in a deadlock. Both thread are waiting on the condition variable. Below is the gdb trace.

(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 pthread_cond_wait@@GLIBC_2.3.2 () from /lib64/libpthread.so.0
 2 Thread 0x7f78bf3b3700 (LWP 8126)  0x00000032b2e0b5bc in  pthread_cond_wait@@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 pthread_cond_wait@@GLIBC_2.3.2 ()
from /lib64/libpthread.so.0
(gdb) bt
#0  0x00000032b2e0b5bc in pthread_cond_wait@@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 pthread_cond_wait@@GLIBC_2.3.2 ()
from /lib64/libpthread.so.0
(gdb) bt
#0  0x00000032b2e0b5bc in pthread_cond_wait@@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 pthread_cond_wait@@GLIBC_2.3.2 ()
from /lib64/libpthread.so.0
(gdb) bt
#0  0x00000032b2e0b5bc in pthread_cond_wait@@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:
smadala@gateway2: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.

Please use the condition variable properly or use semaphore. Semaphore are simple to use in producer consumer problems.

Upvotes: 1

Dunderklaepp
Dunderklaepp

Reputation: 54

The problem that can occur is that thread_A signals before thread_B has reached the pthread_cond_wait statement. Thread_B would never see the signal and instead keep waiting for it.

According to the specs:

The pthread_cond_signal() and pthread_cond_broadcast() functions have no effect if there are no threads currently blocked on cond.

This would result in a deadlock, which is what you are experiencing.

Upvotes: 2

Related Questions