在析构函数中锁定和解锁关键部分以避免崩溃是正确的方法吗?

Posted

技术标签:

【中文标题】在析构函数中锁定和解锁关键部分以避免崩溃是正确的方法吗?【英文标题】:Is Locking and UnLocking CriticalSection in Destructor to avoid crash is right way? 【发布时间】:2013-08-22 13:28:36 【问题描述】:
class MyClass

   ...
   ...
   CCriticalSection m_Cs;

   void MyFunction()
   
      m_Cs.Lock();

      .....

      m_Cs.Unlock(); 


   

   MyClass::~MyClass()
   
     ....

   
;

如上所述,我在我的类中使用关键部分,myFunction 由线程 1 调用,当 myFunction 正在进行时,线程 2 正在删除对象。所以 Unlock 崩溃了。

所以我决定修改 MyClass 析构函数如下

 MyClass::~MyClass()
  

     m_Cs.Lock();
     m_Cs.Unlock(); 
     ....

  

这解决了我的崩溃,因为当线程 1 访问 MyFunction 时,CriticalSection 被锁定,所以当从线程 2 中删除对象时,Destructor 中的 CriticalSection.Lock 被阻塞,直到从 MyFunction 调用解锁。从析构函数中锁定和解锁 CriticalSection 以避免这种崩溃是正确的行为吗?

【问题讨论】:

【参考方案1】:

不,这不是正确的方法,因为它不保护线程 2 在线程 1 调用 MyFunction 之前 删除对象的场景。

您的代码中当前存在Dangling Pointer 错误。

正确的解决方案是修改您的代码,以确保在没有其他线程可以使用该对象时删除该对象。常见的方法包括:

当线程使用对象完成时,使用事件发出信号,执行删除的线程将阻塞等待每个人都说他们完成了。 使用引用计数。让每个使用对象的线程“获取”和“释放”对象。最后一个释放它的对象(例如,当引用计数达到 0 时)然后让对象自行删除。

【讨论】:

感谢@Josh poley 确认这不是正确的方法。是的,我必须管理我的线程不要表现得像这样。我尝试了上述方法,因为这很容易。我只是想确认这是否是正确的方法。

以上是关于在析构函数中锁定和解锁关键部分以避免崩溃是正确的方法吗?的主要内容,如果未能解决你的问题,请参考以下文章

我可以使用联锁操作来更新多个值以避免锁定关键部分/互斥锁吗?

在析构函数中终止当前线程

10分钟后锁定和解锁屏幕时发生的崩溃如何解决?

MySQLi 在析构函数中立即关闭

在析构函数中创建检查类型图

在 Linux 中锁定和解锁用户的 3 种方法