我正在学习C语言中的并发性。我知道有几种方法可以初始化pthread_mutex_t。
这个简单的程序运行良好:
#include <stdio.h>
#include <pthread.h>
pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
void* worker(void* arg) {
pthread_mutex_lock(&lock);
printf("worker says hi\n");
pthread_mutex_unlock(&lock);
return NULL;
}
int main(int argc, char *argv[]) {
pthread_t p;
pthread_create(&p, NULL, worker, NULL);
pthread_mutex_lock(&lock);
printf("master says hi\n");
pthread_mutex_unlock(&lock);
pthread_join(p, NULL);
return 0;
}
但是,如果我不希望全局定义锁,我认为我可以在主线程中定义它并将其传递给另一个线程,如下所示:
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
void* worker(void* arg) {
pthread_mutex_t lock = * (pthread_mutex_t *) arg;
pthread_mutex_lock(&lock);
printf("worker says hi\n");
pthread_mutex_unlock(&lock);
return NULL;
}
int main(int argc, char *argv[]) {
pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
pthread_t p;
pthread_create(&p, NULL, worker, &lock);
pthread_mutex_lock(&lock);
printf("master says hi\n");
pthread_mutex_unlock(&lock);
pthread_join(p, NULL);
return 0;
}
然而,这不工作。相反,它只打印master says hi
并挂起。
我认为这可能是死锁,所以我将一些睡眠时间插入主人,如下所示:
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
void* worker(void* arg) {
pthread_mutex_t lock = * (pthread_mutex_t *) arg;
pthread_mutex_lock(&lock);
printf("worker says hi\n");
pthread_mutex_unlock(&lock);
return NULL;
}
int main(int argc, char *argv[]) {
pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
pthread_t p;
pthread_create(&p, NULL, worker, &lock);
sleep(1);
pthread_mutex_lock(&lock);
printf("master says hi\n");
pthread_mutex_unlock(&lock);
pthread_join(p, NULL);
return 0;
}
正如预期的那样,这打印出worker says hi
,然后在一秒之后打印master says hi
。
但是,如果我将睡眠移动到工作人员,如下所示,它会再次挂起:
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
void* worker(void* arg) {
pthread_mutex_t lock = * (pthread_mutex_t *) arg;
sleep(1);
pthread_mutex_lock(&lock);
printf("worker says hi\n");
pthread_mutex_unlock(&lock);
return NULL;
}
int main(int argc, char *argv[]) {
pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
pthread_t p;
pthread_create(&p, NULL, worker, &lock);
pthread_mutex_lock(&lock);
printf("master says hi\n");
pthread_mutex_unlock(&lock);
pthread_join(p, NULL);
return 0;
}
如果我将睡眠功能置于行<{1}}之上,那么不会挂起。我不确定如何解释这种行为。
答案 0 :(得分:3)
worker
函数正在制作互斥锁的副本,它应该只使用现有的互斥锁。修复是将lock
变量声明为指向互斥锁的指针:
void* worker(void* arg) {
pthread_mutex_t *lock = arg;
pthread_mutex_lock(lock);
printf("worker says hi\n");
pthread_mutex_unlock(lock);
return NULL;
}
答案 1 :(得分:3)
我复制并粘贴了您的所有示例,而不是一个被绞死或显示您的行为。
我不太确定,但我认为问题出在这里的线程函数中:
pthread_mutex_t lock = * (pthread_mutex_t *) arg;
这会创建原始互斥锁的按位副本,具体取决于内容 结构,这可能会导致你看到的问题。因此,glibc + pthreads的不同实现/版本可能会产生不同的结果。
我总是将我的锁作为参数传递给线程,但我没有 问题,但是我没有创建锁的副本,所以我试试这个:
void* worker(void* arg) {
pthread_mutex_t *lock = arg;
pthread_mutex_lock(lock);
printf("worker says hi\n");
pthread_mutex_unlock(lock);
return NULL;
}
这可以解决你的问题。