一个使用pthread_cond_wait出现死锁的问题

vesontio 2014-12-19 04:30:18
在写一个练习,就是最典型的“生产者”(Producer)和“消费者”(Consumer)的问题,两者各用一种线程来代表,各个线程共享一个int类型的数值val。
Producer尝试将val置1,如果发现val已经为1,则wait;
Consumer则尝试将val置0,如果发现val已经为0,则wait;
任意一个线程修改val的值之后,就会呼叫pthread_cond_signal,知会其他线程。
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>

#define TH_POOL_SZ 10
#define TH_NB_LOOP 100

static pthread_mutex_t th_lock = PTHREAD_MUTEX_INITIALIZER;
static pthread_cond_t th_cond = PTHREAD_COND_INITIALIZER;

typedef struct th_data {
int val;
} th_data_t;

程序头就是如此,一个pthread_mutex_t,一个pthread_cond_t,下面的结构体是传递给线程的参数。程序会一共创建TH_POOL_SZ个“生产者”和“消费者”,每个线程尝试循环TH_NB_LOOP次,每次都试着改变val的值。
static void *cons_runnable(void *arg) {
int i;

for (i = 0; i < TH_NB_LOOP; i ++) {
if (pthread_mutex_lock(&th_lock) != 0) {
perror("Failed to lock mutex");
pthread_exit(NULL);
}
printf("Consumer locked.\n");

th_data_t *data = (th_data_t *)arg;
while (data->val == 0) {
printf("Value null, consumer is waiting ...\n");
if (pthread_cond_wait(&th_cond, &th_lock) != 0) {
perror("Failed to wait on mutex");
pthread_exit(NULL);
}
}
printf("Consumer waked up.\n");
data->val --;
printf("Value decremented.\n");

if (pthread_mutex_unlock(&th_lock) != 0) {
perror("Failed to unlock mutex");
pthread_exit(NULL);
}
printf("Consumer unlocked.\n");

if (pthread_cond_signal(&th_cond) != 0) {
perror("Failed to signal other threads");
pthread_exit(NULL);
}
printf("Consumer signaled other threads\n");

}
printf("Consumer terminated.\n");
pthread_exit(NULL);
}

“消费者”(Consumer)的代码,没什么特别的,先加锁,发现val为0就wait,被**后就更新val的值,更新完解锁,并知会其他线程。
static void *prod_runnable(void *arg) {
int i;

for (i = 0; i < TH_NB_LOOP; i ++) {
if (pthread_mutex_lock(&th_lock) != 0) {
perror("Failed to lock mutex");
pthread_exit(NULL);
}
printf("Producer locked.\n");

th_data_t *data = (th_data_t *)arg;
while (data->val == 1) {
printf("Value set, producer is waiting ...\n");
if (pthread_cond_wait(&th_cond, &th_lock) != 0) {
perror("Failed to wait on mutex");
pthread_exit(NULL);
}
}
printf("Producer waked up.\n");
data->val ++;
printf("Value incremented.\n");

if (pthread_mutex_unlock(&th_lock) != 0) {
perror("Failed to unlock mutex");
pthread_exit(NULL);
}
printf("Producer unlocked.\n");

if (pthread_cond_signal(&th_cond) != 0) {
perror("Failed to signal other threads");
pthread_exit(NULL);
}
printf("Producer signaled other threads.\n");
}
printf("Producer terminated.\n");
pthread_exit(NULL);
}

“生产者”(Producer)的代码基本就是和“消费者”(Consumer)反过来。
int main (void) {

int i;
th_data_t data;

pthread_t th_pool_cons[TH_POOL_SZ];
pthread_t th_pool_prod[TH_POOL_SZ];
data.val = 0;

for (i = 0; i < TH_POOL_SZ; i ++) {
if (pthread_create(&th_pool_cons[i], NULL, cons_runnable, &data) != 0) {
perror("Failed to create consumer thread");
return -1;
}
if (pthread_create(&th_pool_prod[i], NULL, prod_runnable, &data) != 0) {
perror("Failed to create producer thread");
return -1;
}
}
printf("%d threads created.\n", TH_POOL_SZ * 2);

for (i = 0; i < TH_POOL_SZ; i ++) {
if (pthread_join(th_pool_cons[i], NULL) != 0) {
perror("Failed to join consumer thread");
return -1;
}
}
for (i = 0; i < TH_POOL_SZ; i ++) {
if (pthread_join(th_pool_prod[i], NULL) != 0) {
perror("Failed to join producer thread");
return -1;
}
}
printf("%d threads joined.\n", TH_POOL_SZ * 2);

printf("Final value of data: %d.\n", data.val);
printf("Fin.\n");
return 0;
}

main函数的话基本就是创建几个线程,然后等着join他们。最后的结果出来,理论上val等于0。但是每次都是在某个“消费者”(Consumer)等待的时候就卡死不动了。
前前后后看了几遍也不知道问题出在神马地方。

希望各路大神们帮帮看看,谢谢!
...全文
919 1 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
1 条回复
切换为时间正序
请发表友善的回复…
发表回复
vesontio 2014-12-19
  • 打赏
  • 举报
回复
已经解决,应当用pthread_cond_broadcast(),而不是pthread_cond_signal(),后者如果没有叫醒正确的线程,会出现所有线程都在wait的情况。

70,028

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧