我正在尝试学习操作系统类中的死锁,而且无论我运行多少次,我制作的程序都不会死锁。代码是:
#include <stdio.h>
#include <pthread.h>
int resource1;
int resource2;
void *causeDeadlock1();
void *causeDeadlock2();
void wait(int r);
void signal(int r);
pthread_t tid[2];
int main()
{
resource1 = 1;
resource2 = 1;
pthread_create((&tid[0]), NULL, &causeDeadlock1, NULL);
pthread_create((&tid[1]), NULL, &causeDeadlock2, NULL);
return(0);
}
void wait(int r)
{
while(r<1);
printf("Done waiting\n");
r--;
}
void signal(int r)
{
r++;
}
void* causeDeadlock1()
{
wait(resource1);
wait(resource2);
printf("Thread 1 is running with both resources.\n");
signal(resource1);
signal(resource2);
printf("Thread 1 is done.\n");
}
void *causeDeadlock2()
{
wait(resource2);
wait(resource1);
printf("Thread 2 is running with both resources.\n");
signal(resource2);
signal(resource1);
printf("Thread 2 is done.\n");
}
当我运行它时,我通常看不到输出,但我也正常返回控制台。我认为原因是线程永远不会打印他们有资源或者他们已经完成,因为他们在wait函数的while循环中永远陷入困境。但是,如果是这样的话,那么程序是否应该挂起而不是让我回到控制台,就像什么都没发生一样?
答案 0 :(得分:3)
您没有获得任何打印输出的原因是主线程正在退出。你应该在从main()
返回之前添加它void *aa;
...
pthread_join(tid[0],&aa);
pthread_join(tid[1],&aa);
return(0);
答案 1 :(得分:2)
您的计划有三个问题。 编辑:四,如果你也算B.沃尔夫的答案。
首先,您的wait
和signal
函数不会导致任何数据争用。它们都不影响真实资源(int r
),但副本作为参数传递。请记住,C使用call-by-value。你应该解决这个问题,例如
void wait(int *r) {
while (*r<1); // still wrong, see below!
(*r)--;
}
void signal(int *r) {
(*r)++;
}
... wait(&resource1);
... signal(&resource1);
其次,即使wait
如上所述发生变化,退出*r >= 1
循环和减量操作的测试while
也应执行原子。否则,两个或多个线程有可能同时获取资源,并且wait
操作的语义存在缺陷。
第三,即使你也解决了第二个问题,你的程序可能死锁,它不会保证死锁。只有当线程的动作以下列方式交错时才会发生死锁:
causeDeadlock1
获取resource1
causeDeadlock2
获取resource2
causeDeadlock1
等待resource2
causeDeadlock2
等待resource1
重要的是1和2(以任何相对顺序)在3和4之前发生(再次以任何相对顺序)。
大多数情况下,我会期望获取其第一个资源的线程也能够在另一个线程甚至有机会开始执行之前设法获取第二个资源。因此,如果你只运行一次,我不会打赌陷入僵局。将函数causeDeadlock1
和causeDeadlock2
的主体放在循环中,你肯定会看到一个死锁(在你解决了其他两个问题之后)。