如果我不加入发布版本中的“破坏”线程怎么办?

Posted

技术标签:

【中文标题】如果我不加入发布版本中的“破坏”线程怎么办?【英文标题】:What if I don't join thread on "destruction" in release builds? 【发布时间】:2010-09-08 16:37:06 【问题描述】:

在许多情况下,我的类就像活动对象(有一个线程)。并且为了避免访问冲突,我总是必须等待加入析构函数。这通常不是问题。

但是,想象一个带有一些错误(死锁、活锁等)的发布版本会导致 join() 不能按时返回或根本不返回,这将导致整个应用程序在等待一个不会运行的对象时变得无法正常工作再次使用。如果这种情况发生在客户身上,它就会成为一个问题。

我宁愿收到问题通知并跳过加入。并泄漏线程及其资源。

跳过连接可以通过这样的方式来实现。

   class MyActiveObject
    
    public:
        MyActiveObject();
        ~MyActiveObject()
    private
        struct Implementation;
        std::shared_ptr<Implementation> pImpl_;
    ;

    struct MyActiveObject::Implementation : std::enable_shared_from_this<Implementation >
    
        Implementation() : thread_([=]Run();)
        
        

        ~Implementation()
        
            #ifdef _DEBUG
                thread_.join();
            #else
                if(!thread_.timed_join(SOME_TIMEOUT))
                    ALERT_SOME_HOW();
            #endif
        

        void Dispose()
        
            isRunning_ = false;
        

        void Run()
        
        #ifndef _DEBUG
            auto pKeepAlive = shared_from_this(); // Won't be destroyed until thread finishes
        #endif   
            isRunning_ = true;
            while(isRunning_)
            
                 /* ... */
            
        

        boost::thread thread_;
        tbb::atomic<bool> isRunning_;
    ;

MyActiveObject::MyActiveObject() : pImpl_(new Implementation())
MyActiveObject::~MyActiveObject()  pImpl_->Dispose(); 

这是个好主意吗?还是有更好的策略?

【问题讨论】:

【参考方案1】:

奇怪的问题:'如果我的代码中有错误,我就有问题'。嗯,是。修复错误,不要试图将其覆盖。这种论文只会产生两个错误,因为在您知道第一个错误是什么之前,您无法对其进行测试。

【讨论】:

+1 - 如果你的线程留下锁,你无论如何都会遇到问题。修复真正的问题 尽管我同意你的看法。仍然存在在测试期间并不总是检测到某些类型的错误(尤其是在谈论多线程时)的问题。 好吧,不要做太多,大声喊叫和崩溃,这样你就知道了。 这种计时器正是开始大喊大叫所需要的。 @ronag:问题不在于是否在测试期间检测到错误,而是当它们发生时,您的应用程序将无法正常工作无论如何 i> 你必须解决它并将其覆盖。如果你有一个从未释放的锁,无论你是否在线程上调用join,都会造成严重破坏。【参考方案2】:

如果可行,最好激活某种结构分析来找到循环并打破僵局。

它可能会错过一些销毁时的死锁,但它也可能适用于捕获该上下文之外的死锁。

【讨论】:

关于“某种结构分析”您是否愿意更详细一点? @ronag:如果您有两个未终止的线程对象并且彼此之间有明显的指针,您可以尝试检测并执行某些操作。这取决于很多。【参考方案3】:

如果您正在编写客户端应用程序并且在此销毁序列之后应用程序的生命周期很短,那么这似乎是一个合理的实用解决方案。我鼓励您添加一些日志记录并尝试收集发布日志(至少来自您的内部测试)。

如果您正在编写服务器应用程序并且这种破坏不是在服务器关闭期间进行的,那么我不鼓励这种行为,因为您的服务器经常耗尽资源不太可能是好的。

在这两种情况下,任何已知的死锁问题都应该由开发团队以高优先级进行处理 - 即使对客户隐藏了影响。

【讨论】:

以上是关于如果我不加入发布版本中的“破坏”线程怎么办?的主要内容,如果未能解决你的问题,请参考以下文章

我怎么知道线程是不是是可连接线程?

access数据库被破坏,如何修复?

mysql udf函数怎么调用

Qt 软件中怎么自动加入build版本号

将 Bootstrap 更新到版本 3 - 我该怎么办?

python 爬虫加入线程池问题