如何解决 C++ 中的未释放锁问题
Posted
技术标签:
【中文标题】如何解决 C++ 中的未释放锁问题【英文标题】:How to solve unreleased lock issue in C++ 【发布时间】:2013-07-20 01:54:07 【问题描述】:如果可能的话,请有人通过参考或示例帮助我解决 C++ 中的死锁问题。
场景如下。
线程1被互斥锁锁定并做一些操作,线程2和线程3处于等待线程1解锁访问资源的状态。
发生了一些中止/意外的事情——线程 1 被终止并且没有获得解锁,线程 2 和线程 3 仍在等待。
在这种情况下如何保存主线程(意味着主线程应该不会发生任何事情)。
请说明如何在 c++ 中解决此类问题。
谢谢, 酋长
【问题讨论】:
你能展示一些代码来说明你是如何在 c++ 中使用线程的吗? “保存主线程”是什么意思?展示一个小的、可编译的代码示例将非常有帮助 为什么投反对票?这是一个有价值且严肃的问题(可能超出了反对者的概念)! 这不是死锁。死锁是一个循环的锁链。这只是一个未释放的锁,即锁泄漏。解决方案与任何其他资源泄漏相同。 修复线程 1 怎么样? 【参考方案1】:发生了一些中止/意外的事情
使用某物。像std::lock_guard
这样可以防止由于异常或忘记/意外但必要的unlock()
操作而“挂起”锁。
原理非常简单,您可以轻松地为任何使用一对以“锁定/解锁”方式对应在一起的方法的机制实现它:
class LockObject // E.g. mutex or alike
public:
// ...
void lock();
void unlock();
;
将保护类构造函数绑定到对锁对象实例的引用,并在构造函数中调用lock()
,在析构函数中调用unlock()
:
template<typename T>
class LockGuard
public:
LockGuard(T& lockObject)
: lockObject_(lockObject)
lockObject_.lock();
~LockGuard()
lockObject_.unlock();
private:
T& lockObject_;
;
像这样使用LockGuard
:
// Some scope providing 'LockObject lockObject'
LockGuard<LockObject> lock(lockObject)
// Do s.th. when lockObject is locked
// Call of lockObject.unlock() is guaranteed at least here, no matter what
// (exception, goto, break, etc.) caused leaving the block's scope.
【讨论】:
但是如果线程被杀死会调用析构函数 @RyanHaining If s.th.就像thread::kill()
操作可用(特定于操作系统?)我希望它能够正确展开堆栈!
@RyanHaining 从外部杀死线程在 C/C++ 中是一个相当糟糕的主意。 C++11 的线程 API 一开始就不允许这样做是有原因的。终止线程的正确方法是实现一种机制来发出终止请求信号,然后允许线程自行关闭。
@ComicSansMS 我知道杀死线程是一件可怕的事情,尽管如此,我认为问题是如果一个线程在持有互斥锁时被杀死,有没有办法去解锁它?。这仍然是一个可靠的答案【参考方案2】:
通常线程不应意外终止。您可以尝试使用 try/catch 块。如果您仍然想在线程意外终止时释放资源,您可以创建一个等待第一个线程终止的监控线程。
在 Windows 上,您可以使用 ::WaitForSingleObject(m_htThread, INFINITE)。
一旦第一个线程被终止,您就可以继续释放废弃的锁。 也许您需要添加一些标志来指示终止是否正常。 您可能还必须记住哪个线程正在锁定哪个对象。
如前所述,我不建议使用这种方法,但在极端情况下。
【讨论】:
【参考方案3】:任何语言或平台解决死锁的方法都是一样的。
始终以相同的顺序获取锁。
编辑:但是您错误地描述了您的问题。这不是僵局。死锁是一个循环的锁链。这只是一个未释放的锁,即锁泄漏。解决方案与任何其他资源泄漏相同:不要。在 C++ 中,这意味着在析构函数中释放资源,并确保调用析构函数。不知何故,您的线程在没有这样做的情况下终止了。找到那个问题并修复它。
【讨论】:
但是他的问题是有一个锁没有被释放,而不是他以错误的顺序获得了第二个锁。所以在这种情况下这不是正确的解决方案。 致谁反对这个:这完全正确,但可能与 OP 描述的情况不符(我认为这是更简单的原因)。 @g-makulik 显然这是一个正确的陈述,但它与 OPs 问题无关。任何未解决该问题的答案都会遭到反对。在这种情况下只有一个锁。 @RyanHaining '但这与 OP 的问题无关' 是的!你是对的!但无论如何,我认为它不值得被否决。这是正确处理死锁(至少在问题标题中提到)的一个重要方面,并且可能会启发 OP 走上他的道路;o) ... @WanderingLogic 在这种情况下,问题根本不是死锁。以上是关于如何解决 C++ 中的未释放锁问题的主要内容,如果未能解决你的问题,请参考以下文章
如何解决反应身份验证中的未捕获(承诺中)TypeError?
如何解决 NSScanner 上的“架构 x86_64 的未定义符号”? react-native 中的 Swift pod