练习程序不按预期制造死锁
Practice program not making deadlock as intended
我正在尝试了解我的操作系统中的死锁 class,并且无论我 运行 多少次,我编写的程序都没有死锁。代码是:
#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");
}
当我 运行 它时,我通常看不到任何输出,但我也正常返回到控制台。我认为这是因为线程永远无法打印出它们拥有资源或它们已完成,因为它们永远卡在等待函数的 while 循环中。但是,如果是这样的话,程序不应该挂起而不是让我像什么都没发生一样返回到控制台吗?
您的程序存在三个问题。 编辑: 四个,如果你也算上 B. Wolf 的回答。
首先,您的 wait
和 signal
函数不会导致任何数据竞争。它们都不会影响实际资源 (int r
),但会影响作为参数传递的副本。请记住,C 使用按值调用。你应该解决这个问题,例如
void wait(int *r) {
while (*r<1); // still wrong, see below!
(*r)--;
}
void signal(int *r) {
(*r)++;
}
... wait(&resource1);
... signal(&resource1);
其次,即使wait
如上更改,退出while
循环和自减操作的测试*r >= 1
也应该原子地执行。否则,两个或多个线程可能会同时获取资源,并且您的 wait
操作的语义存在缺陷。
第三,即使你也修复了第二个问题,你的程序可能死锁,保证死锁。仅当线程的操作以下列方式交错时才会发生死锁:
causeDeadlock1
获得 resource1
causeDeadlock2
获得 resource2
causeDeadlock1
等待resource2
causeDeadlock2
等待resource1
重要的是 1 和 2(以任何相对顺序)发生在 3 和 4(同样以任何相对顺序)之前。
大多数情况下,我希望获取其第一个资源的线程也能设法获取第二个资源,甚至在另一个线程有机会开始执行之前。因此,如果您只 运行 这一次,我不会打赌会出现僵局。将函数体 causeDeadlock1
和 causeDeadlock2
放入循环中,您肯定会看到死锁(在解决其他两个问题之后)。
您没有得到任何打印输出的原因是主线程正在退出。您应该在从 main()
返回之前添加它
void *aa;
...
pthread_join(tid[0],&aa);
pthread_join(tid[1],&aa);
return(0);
我正在尝试了解我的操作系统中的死锁 class,并且无论我 运行 多少次,我编写的程序都没有死锁。代码是:
#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");
}
当我 运行 它时,我通常看不到任何输出,但我也正常返回到控制台。我认为这是因为线程永远无法打印出它们拥有资源或它们已完成,因为它们永远卡在等待函数的 while 循环中。但是,如果是这样的话,程序不应该挂起而不是让我像什么都没发生一样返回到控制台吗?
您的程序存在三个问题。 编辑: 四个,如果你也算上 B. Wolf 的回答。
首先,您的 wait
和 signal
函数不会导致任何数据竞争。它们都不会影响实际资源 (int r
),但会影响作为参数传递的副本。请记住,C 使用按值调用。你应该解决这个问题,例如
void wait(int *r) {
while (*r<1); // still wrong, see below!
(*r)--;
}
void signal(int *r) {
(*r)++;
}
... wait(&resource1);
... signal(&resource1);
其次,即使wait
如上更改,退出while
循环和自减操作的测试*r >= 1
也应该原子地执行。否则,两个或多个线程可能会同时获取资源,并且您的 wait
操作的语义存在缺陷。
第三,即使你也修复了第二个问题,你的程序可能死锁,保证死锁。仅当线程的操作以下列方式交错时才会发生死锁:
causeDeadlock1
获得resource1
causeDeadlock2
获得resource2
causeDeadlock1
等待resource2
causeDeadlock2
等待resource1
重要的是 1 和 2(以任何相对顺序)发生在 3 和 4(同样以任何相对顺序)之前。
大多数情况下,我希望获取其第一个资源的线程也能设法获取第二个资源,甚至在另一个线程有机会开始执行之前。因此,如果您只 运行 这一次,我不会打赌会出现僵局。将函数体 causeDeadlock1
和 causeDeadlock2
放入循环中,您肯定会看到死锁(在解决其他两个问题之后)。
您没有得到任何打印输出的原因是主线程正在退出。您应该在从 main()
返回之前添加它void *aa;
...
pthread_join(tid[0],&aa);
pthread_join(tid[1],&aa);
return(0);