【问题标题】:Why does this code lead to deadlock?为什么这段代码会导致死锁?
【发布时间】:2012-08-27 20:09:09
【问题描述】:

我很惊讶地从pstack 看到这段代码导致了死锁!我没有看到同样的原因。

pthread_mutex_t lock;

_Cilk_for (int i = 0; i < N; ++i) {
  int ai = A[i];
  if (ai < pivot) {
    pthread_mutex_lock(&lock);
    A[ia++] = ai;
    pthread_mutex_unlock(&lock);
  }
  else if (ai > pivot) {
    pthread_mutex_lock(&lock);
    A[ib++] = ai;
    pthread_mutex_unlock(&lock);
  }
  else {
    pthread_mutex_lock(&lock);
    A[ic++] = ai;
    pthread_mutex_unlock(&lock);
  }
}

我只是使用互斥锁来确保对 A 的访问是原子的和序列化的。

  • 这段代码有什么问题导致死锁?
  • 有没有更好的方法来实现这一点?

【问题讨论】:

  • 旁注:这看起来像是一种实现并行快速排序的可怕方式?
  • 你在lock上打电话给pthread_mutex_init吗?
  • 这段代码不会死锁。死锁至少需要在尝试获取另一个锁时持有一个锁。你永远不会那样做。
  • 但是,它就在我面前陷入僵局。

标签: c++ pthreads deadlock cilk cilk-plus


【解决方案1】:

如果这是函数内的代码,那么您没有正确初始化互斥锁。您需要将其设置为PTHREAD_MUTEX_INITIALIZER(对于简单的默认互斥锁)或对其执行pthread_mutex_init()(对于更复杂的要求)。如果没有正确的初始化,您将不知道互斥锁从什么状态开始 - 它很可能处于锁定状态,因为该位置的堆栈上发生的任何事情看起来都像是一个锁定的互斥锁。

这就是为什么它总是需要以某种方式初始化,以便对初始状态毫无疑问。

您可能遇到的另一个潜在问题是:

int ai = A[i];

可能应该使用相同的互斥锁来保护该访问,否则您可能会在“半状态”下读取它(当另一个线程只是更新变量的一部分时)。


而且,我不得不说,我不确定这里是否明智地使用了线程。互斥锁的使用可能会淹没像A[ia++] = ai 这样的语句,以至于绝大多数时间都花在锁定和解锁互斥锁上。它们通常在锁定期间正在处理的代码更大量的情况下更有用。

您可能会发现一个非线程变体会将这个变体从水中吹走(但是,当然,不要相信我的话 - 我的主要优化口号是 “测量,不要猜测” )。

【讨论】:

  • 谢谢,这个可行,但我不明白,lock 的值有什么关系?
  • @paxdiablo:知道为什么缺少 init() 会导致死锁吗?我很确定这是一个僵局。
  • @Lazer:是的,如果没有按照 pthreads doco 进行适当的初始化,您将不知道初始状态。据我们所知,它可能开始处于锁定状态,因为这是您分配它时堆栈上的内容。查看更新。
【解决方案2】:

在您修复或以其他方式验证您实际上正在初始化您的 lock 之后:

pstack 可能知道_Cilk_for 引入的控制机制会干扰原本合理的pthread 代码。

快速搜索显示有mutex solutions for use with Cilk - 没有提到混合 Cilk 和 pthreads。看起来 Cilk 是 pthreads 之上的一层——所以如果 Cilk 选择在mutex, 周围放置一个包装器,他们这样做可能是有充分理由的。我建议继续使用 Cilk API。

除此之外,您的算法还有一个更根本的问题。 在您的情况下, 创建并行线程和同步它们的开销可能会使执行 for 循环主体中的代码的成本相形见绌。在不并行化的情况下,这很有可能运行得更快。

【讨论】:

  • 是的,事实上,对于某些工作负载,这比串行版本慢 10 倍。
【解决方案3】:

您的pthread_mutex_t lock 未正确初始化,因此,由于它是一个局部变量,它可能包含垃圾,并且可能处于奇怪的锁定状态。您应该调用pthread_mutex_init 或使用PTHREAD_MUTEX_INITIALIZER 初始化您的lock

正如其他人抱怨的那样,您没有明智地使用互斥锁。代码的关键部分太小了。

【讨论】:

    猜你喜欢
    • 2020-08-20
    • 1970-01-01
    • 2019-12-27
    • 1970-01-01
    • 1970-01-01
    • 2017-11-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多