了解并避免多线程应用程序中嵌套锁的危险

时间:2012-02-12 00:04:17

标签: c++ multithreading qt

我对多线程仍然相当新,但已经多次烧过。 现在我尽量避免一些陷阱,但我很难做到以下几点:

考虑几个线程,线程A生产者,因此writer,线程BC,...因此消费者线程reader。 所有人都共享一个公共缓冲区S

一些基本书籍建议为此场景引入所谓的ReadWriteLock。 多个并发读取是可能的,但显然只有一个write.Boost也提供了这样的锁,Qt。

让我们假设两个函数f1和f2锁定S进行读取。 在线程B中调用f1并锁定读取,f1在f1内调用并锁定以便再次读取,因此嵌套锁定是可能的。

现在考虑f1执行的瞬间并首次锁定读取。如果线程A被调用并想要写入,则会被阻止。 此外,如果内部f1 f2被调用并且想要锁定它,因为阻塞的writer正在等待,在这种情况下,许多锁(例如QReadWriteLock)也会阻塞readers。 因此,我们得到了一个非常令人讨厌的死锁,这个死锁是不可预测的,只有当writer在f1中的锁定和f2的锁定之间发生时才会发生。

我目前避免此类错误的方法是一个调试工具,它跟踪锁定并断言如果同一个线程试图锁定读取两次,但这非常麻烦。 除此之外,我避免将大量代码放入锁中,这有助于我的团队中的其他成员忽略。

可以使用哪些其他功能来预防此类情况? 为什么ReadWriteLocks允许它们呢? 在设计阶段是否有一些通用的经验法则可以避免上述情况?

提前感谢您阅读长篇问题; - )

1 个答案:

答案 0 :(得分:0)

也许你可以使用QReadWriteLock中的tryReadLock函数。防止死锁。

如果它无法锁定读取..然后解锁读取的互斥锁。

在某些情况下,它可能会丢失要读取的数据,如果您不想丢失任何要读取的数据,可以通过添加标记或ID号或其他内容来识别您的失败读取作业并将其放入堆栈,所以写完线程完成他的工作后,你将能够恢复你的阅读事情从一个失败的开始。它会使您最大限度地减少损失数据..

我希望它会有所帮助。

我的英语不好。