当前位置: 首页 > 知识库问答 >
问题:

pthread_cond_wait奇怪的行为

何昆
2023-03-14

我在用C来解决这个问题。

代码是使用g-lpthon编译的。

整个解决方案都在github上。存储库包含两个cpp文件:main。cpp和哲学家。cpp。“Main.cpp”创建互斥变量、信号量、5个条件变量、5个分叉并启动。信号量仅用于同步开始时间。其他参数被传递给哲学家来解决问题。“哲学家.cpp”包含给定问题的解决方案,但经过几个步骤后,死锁就会发生。

当哲学家0正在吃饭,而哲学家1(在他旁边)想要拿叉子时,就会发生死锁。然后,哲学家1已经获取了互斥,并且在哲学家0放下叉子之前不会将其返回。哲学家0无法放下他的叉子,因为使用了互斥,所以出现了死锁。问题出在哲学家::take_fork方法中,对pthread_cond_wait(a,b)的调用没有释放互斥体b。不知道为什么?

// Taking fork. If eather lef or right fork is taken, wait.
void Philosopher::take_fork(){
  pthread_mutex_lock(&mon);
  std::cout << "Philosopher " << id << " is waiting on forks" << std::endl;
  while(!fork[id] || !fork[(id + 1)%N])
    pthread_cond_wait(cond + id, &mon);
  fork[id] = fork[(id + 1)%N] = false;
  std::cout << "Philosopher " << id << " is eating" << std::endl;
  pthread_mutex_unlock(&mon);
}

其余部分请参考此代码。

共有1个答案

宋成天
2023-03-14

您对pthread\u cond\u wait()的调用没有问题,因此问题一定在别处。我可以看到您有三个bug:

首先,在main()。您需要初始化所有N条件变量:

for(int i = 0; i < N; i++) {
    fork[i] = true;
    pthread_cond_init(&cond[i], NULL);
}

pthread_mutex_init(&mon, NULL);

其次,在put_fork()中,您对要发出信号的一个条件变量的计算不正确:

pthread_cond_signal(cond + (id-1)%N);    /* incorrect */

id等于零时,(id-1)%N等于-1,因此这将尝试发出信号cond-1,该信号不指向条件变量(该指针实际上可能会损坏互斥锁,因为它可能直接放在堆栈上的cond之前)。您实际需要的计算是:

pthread_cond_signal(cond + (id + N - 1) % N);

第三个bug不是死锁的原因,但您不应该每次调用rand(),都调用srand(time(NULL))——只需在main()的开头调用一次即可。

 类似资料:
  • 我有以下代码来解析一个JSON文件: 要处理以下JSON文件: 如果我执行此代码,我将收到以下错误: 所以我开始一步一步地调试应用程序,看看part processing()中的哪个代码部分抛出了这个异常。令人惊讶的是,那里的所有代码都正常执行:没有抛出异常,也没有返回结果I except。 更让我惊讶的是,当我稍微改变第一种方法的代码时,它可以在不产生异常的情况下工作。 我不知道println方

  • 问题内容: 我在GregorianCalendar类中遇到一个奇怪的行为,我想知道我是否真的做得不好。 仅当初始化日期的月份的实际Maximum大于我将日历设置为的月份时,才追加此值。 这是示例代码: 我知道问题是由于日历初始化日期是31天(可能是5月),与设置为2月(28天)的月份混淆了。修复很容易(只需在设置年和月之前将day_of_month设置为1),但是我想知道这确实是想要的行为。有什么

  • 问题内容: 我正在为一个问题而苦苦挣扎,我不明白为什么它不起作用。如何通过将变量传递并转换为? 为什么在顶部代码段中不起作用,但在行下方的底部代码段中起作用? 唯一的区别似乎是添加了一个额外的变量,该变量也被键入为? 问题答案: 该是一种原始类型,同时是一个普通的Java类。您不能在原始类型上调用方法。但是该方法在上可用,如javadoc中所示 有关这些原始类型的更多信息,请参见此处

  • 问题内容: 为什么的到哪里去了? 问题答案: 删除任何字符,并从字符串的开头和结尾。

  • 问题内容: 我认为这是一个正常程序,但这是我得到的输出: 有人可以向我解释一下吗? 问题答案: 这是有据可查的PHP行为,请参阅php.net的foreach页面上的警告。 警告 即使在 foreach 循环之后,仍保留 $ value的 引用和最后一个数组元素。建议通过unset()销毁它。 __ 编辑 尝试逐步了解此处实际发生的情况

  • 问题内容: 我有上面的代码,但我不知道为什么会产生 而不是 非常感谢 问题答案: 使用量词来匹配1个或多个空格,而不是:- 表示匹配0个或多个空格,并且将在每个字符之前匹配一个空字符,并由一个空格代替。