好的..这是关于这个问题的一些背景知识。我有一些“关键”代码,我试图用互斥锁保护。它就是这样的
Mutex.Lock()
//关键代码 //某个文件IO
Mutex.Unlock()。
现在的问题是,由于这个问题,我的程序似乎“卡住了”。让我用一个例子来解释。
Thread_1进来;并转到Mutex.Lock()并开始执行关键代码。在关键代码中;它需要做一些文件IO。现在就在这一点上;我相信'上下文切换'发生并且Thread_2进入并阻塞Mutex.Lock()(因为Thread_1具有锁定)。一切似乎都很好,但就我而言;程序'挂起'在这里..我唯一能想到的是,不知何故Thread_2会一直阻塞并且不会切换回Thread_1 ??
更多信息:在linux上使用pthread_mutex_init和pthread_mutex_lock。
答案 0 :(得分: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
}
...
答案 1 :(得分:2)
这听起来像deadlock,其中Thread_1在mutext中并等待Thread_2释放某些,而Thread_2正在等待进入互斥锁,因此无法释放它是什么Thread_1需要的。
编辑:交换的线程名称更接近匹配问题中的场景,添加'在互斥锁中'
答案 2 :(得分:1)
这样的最佳解决方案是使用调试器(gdb?)。如果您使用任何带调试器的IDE(eclipse?)来使调试更容易和更直观,那就更好了。
像这样你会看到每个线程都在等待的位置。
我期望Thread1锁定互斥锁进入临界区,卡在IO中(可能是错误的读取或无限循环),线程2通常等待互斥锁被解锁。
这似乎不是死锁,因为单个互斥锁不会发生死锁!
答案 3 :(得分:0)
只要只有一个锁,上下文切换就无关紧要了。另一个线程无法做任何事情来影响第一个线程,因为它只是等待锁定才能获得它。所以问题在于第一个线程以某种方式。调试器对于多线程来说几乎一文不值,但死锁通常很容易解决,因为有人指出可能第一个线程在某种程度上处于无限循环中。
答案 4 :(得分:0)
文件I / O是否需要成为关键部分的一部分?如果线程1正在执行阻塞读取,并且线程2应该写入该文件(或管道或类似物),则线程1将永远不会返回以释放互斥锁。您应该评估关键部分,以确定互斥锁实际需要保护的内容。让关键部分尽可能小是一种良好的做法。