练习程序不按预期制造死锁

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 的回答。

首先,您的 waitsignal 函数不会导致任何数据竞争。它们都不会影响实际资源 (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 操作的语义存在缺陷。

第三,即使你也修复了第二个问题,你的程序可能死锁,保证死锁。仅当线程的操作以下列方式交错时才会发生死锁:

  1. causeDeadlock1 获得 resource1
  2. causeDeadlock2 获得 resource2
  3. causeDeadlock1等待resource2
  4. causeDeadlock2等待resource1

重要的是 1 和 2(以任何相对顺序)发生在 3 和 4(同样以任何相对顺序)之前。

大多数情况下,我希望获取其第一个资源的线程也能设法获取第二个资源,甚至在另一个线程有机会开始执行之前。因此,如果您只 运行 这一次,我不会打赌会出现僵局。将函数体 causeDeadlock1causeDeadlock2 放入循环中,您肯定会看到死锁(在解决其他两个问题之后)。

您没有得到任何打印输出的原因是主线程正在退出。您应该在从 main()

返回之前添加它
void *aa;
...
pthread_join(tid[0],&aa);
pthread_join(tid[1],&aa);

return(0);