C:生产者/消费者
C: Producer / Consumer
我在学校的任务之一是修复这段代码。生产者和消费者线程应该交替增加他们的局部变量并将其打印出来,但我不知道如何修复它。
生产者和消费者线程应该可以无限期地这样做,但如果我启动可执行文件,它会任意停止。
如果有人能向我解释这种行为,那就太好了。
代码如下:
#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...
....
可能出现的问题是 thread_A 在 thread_B 到达 pthread_cond_wait
语句之前发出信号。 Thread_B 永远不会看到信号,而是继续等待。
根据 specs:
The pthread_cond_signal() and pthread_cond_broadcast() functions have no effect if there are no threads currently blocked on cond.
这会导致死锁,这就是您遇到的情况。
我已经执行了游览代码。这导致了僵局。
两个线程都在等待条件变量。
下面是 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 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.
请正确使用条件变量或使用信号量。信号量在生产者消费者问题中使用起来很简单。
我在学校的任务之一是修复这段代码。生产者和消费者线程应该交替增加他们的局部变量并将其打印出来,但我不知道如何修复它。
生产者和消费者线程应该可以无限期地这样做,但如果我启动可执行文件,它会任意停止。
如果有人能向我解释这种行为,那就太好了。
代码如下:
#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...
....
可能出现的问题是 thread_A 在 thread_B 到达 pthread_cond_wait
语句之前发出信号。 Thread_B 永远不会看到信号,而是继续等待。
根据 specs:
The pthread_cond_signal() and pthread_cond_broadcast() functions have no effect if there are no threads currently blocked on cond.
这会导致死锁,这就是您遇到的情况。
我已经执行了游览代码。这导致了僵局。 两个线程都在等待条件变量。 下面是 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 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.
请正确使用条件变量或使用信号量。信号量在生产者消费者问题中使用起来很简单。