0

好的..这里是这个问题的一些背景。我有一些我试图用互斥锁保护的“关键”代码。它是这样的

互斥锁()

// 关键代码 // 一些文件 IO

互斥锁()。

现在的问题是我的程序似乎因此而“卡住”了。让我用一个例子来解释。

Thread_1 进来;然后转到 Mutex.Lock() 并开始执行关键代码。在关键代码中;它需要做一些文件 IO。现在在这一点上;我相信会发生“上下文切换”并且 Thread_2 进入并阻塞 Mutex.Lock() (因为 Thread_1 有锁)。一切似乎都很好,但就我而言;程序在这里“挂起”。我唯一能想到的是,不知何故 Thread_2 一直阻塞并且不会切换回 Thread_1?

更多信息:在 linux 上使用 pthread_mutex_init 和 pthread_mutex_lock。

4

5 回答 5

5

正如其他人所提到的,您可能遇到了僵局。

边注:

您需要确保在关键代码块中没有任何未捕获的异常。否则锁永远不会被释放。您可以使用RAII锁来解决此问题:

class SingleLock {
public:
  SingleLock(Mutex &m) : m(m) { m.Lock(); }
  ~SingleLock() { m.Unlock(); }
private:
  Mutex m;
};

...
{ 
  SingleLock lock(mutex);
  // critical code // some file IO

}
...
于 2009-12-28T22:25:53.950 回答
2

这听起来像是一个死锁,其中 Thread_1 在互斥锁中并等待 Thread_2 释放某些东西,而 Thread_2 正在等待进入互斥锁,因此无法释放 Thread_1 需要的任何东西。

编辑:交换线程名称以更紧密地匹配问题中的场景,添加“在互斥锁中”

于 2009-12-28T21:55:28.320 回答
1

此类问题的最佳解决方案是使用调试器 ( gdb? )。最好使用带有调试器(eclipse?)的任何 IDE,以使调试更容易和更直观。

像这样,您将看到每个线程正在等待的位置。

我期望的是线程1锁定互斥锁进入临界区,卡在IO中(可能是错误读取或无限循环)而线程二通常正在等待互斥锁被解锁。

看起来这不是死锁,因为单个互斥锁不可能发生死锁!

于 2009-12-28T22:19:01.203 回答
0

只要只有一个锁,上下文切换就无关紧要。另一个线程不能做任何事情来影响第一个线程,因为它只会等待锁直到它得到它。所以问题出在第一个线程上。调试器对于多线程几乎毫无价值,但死锁通常很容易解决,正如有人指出的那样,第一个线程可能以某种方式处于无限循环中。

于 2009-12-28T22:24:49.303 回答
0

文件 I/O 是否需要成为关键部分的一部分?如果线程 1 正在执行阻塞读取,并且线程 2 应该写入该文件(或管道或类似文件),那么线程 1 将永远不会返回以释放互斥锁。您应该评估您的关键部分以确定互斥锁实际需要保护的内容。让您的关键部分尽可能小被认为是一种很好的做法。

于 2009-12-28T22:27:43.993 回答