C++ 为什么这段代码会导致死锁?

C++ 为什么这段代码会导致死锁?,c++,pthreads,deadlock,cilk,cilk-plus,C++,Pthreads,Deadlock,Cilk,Cilk Plus,我很惊讶地从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 > p

我很惊讶地从
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);
  }
}
pthread\u mutex\u t lock;
_(int i=0;i枢轴){
pthread_mutex_lock(&lock);
A[ib++]=ai;
pthread_mutex_unlock(&lock);
}
否则{
pthread_mutex_lock(&lock);
A[ic++]=ai;
pthread_mutex_unlock(&lock);
}
}
我只是使用互斥体来确保对的访问是原子的和序列化的

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

您的
pthread\u mutex\u t lock
未正确初始化,因此,由于它是一个局部变量,它可能包含垃圾,并且可能处于奇怪的锁定状态。您应该使用
PTHREAD\u MUTEX\u初始值设定项调用或初始化
lock


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

如果这是函数中的代码,那么您没有正确初始化互斥体。您需要将其设置为
PTHREAD\u MUTEX\u INITIALIZER
(对于简单的默认互斥),或者对其执行
PTHREAD\u MUTEX\u init()
(对于更复杂的需求)。如果没有适当的初始化,您就不知道互斥锁的启动状态——它很可能处于锁定状态,因为堆栈上该位置发生的任何事情看起来都像是锁定的互斥锁

这就是为什么它总是需要以某种方式初始化,这样就不存在初始状态的疑问

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

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


而且,我不得不说,我不确定线程在这里是否被明智地使用。互斥锁的使用很可能会淹没像
a[ia++]=ai
这样的语句,以至于大部分时间都会花在锁定和解锁互斥锁上。在锁期间处理的代码稍微丰富一些的情况下,它们通常更有用


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

在修复或验证您实际上正在初始化
锁之后:

pstack
可能与
\Cilk\u为
引入的控制机制有关,这些机制干扰了原本合理的
pthread
代码

通过快速搜索可以发现有两个线程-没有提到混合使用Cilk和pthreads。看起来Cilk确实是pthreads之上的一层——因此,如果Cilk选择在
互斥体周围放置一个包装器,
他们这样做可能是有充分理由的。我建议继续使用Cilk API


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

旁注:这看起来是一种可怕的实现并行快速排序的方法?您是否在
锁上调用
pthread\u mutex\u init
?此代码不会死锁。死锁至少需要在尝试获取另一个锁时持有一个锁。你从来没有这样做过。但是,它就在我面前死锁了。谢谢,这是可行的,但我不明白,锁的值有什么关系?@paxdiablo:知道为什么缺少init()会导致死锁吗?我很确定这是一个死锁。@Lazer:是的,没有按照pthreads doco进行正确的初始化,您不知道初始状态。据我们所知,它可能以锁定状态启动,这仅仅是因为当您分配它时,堆栈上就是锁定状态。请参阅更新。是的,事实上,对于某些工作负载,这比串行版本慢10倍。