函数静态变量析构函数和线程

Posted

技术标签:

【中文标题】函数静态变量析构函数和线程【英文标题】:function static variable destructor and thread 【发布时间】:2013-06-21 16:09:54 【问题描述】:

我有一个简单的程序。

int main() 

    std::atomic<bool> b = true;
    ConcurrentQueue<std::string> queue;

    std::thread thread( [&]
        while ( b ) 
            auto str = queue.wait_and_pop();
            std::cout << *str;
        
    );

    b = false;
    queue.push( "end" );
    thread.join();

ConcurrentQueue&lt;T&gt; 是我自己实现的线程安全队列,wait_and_pop 是使用std::condition_variable 的阻塞操作。

这个程序成功打印“end”并退出,这里没有问题。 (有一个错误,当thread 启动时b 为假,导致它立即退出,但这与此处无关)

但是如果我将所有这些都包装在一个类中

class object 
public:
    object() 
        b = true;

        thread = std::thread( [this]
            while ( b ) 
                auto str = queue.wait_and_pop();
                std::cout << *str;
            
        );
    

    ~object() 
        b = false;
        queue.push( "end" );
        thread.join();
    

private:
    std::atomic<bool> b;
    std::thread thread;
    ConcurrentQueue<std::string> queue;
;

并有一个函数静态变量,如

object & func() 
  static object o;
  return o;

和主要的

int main() 
    object & o = func();

现在程序打印“end”然后卡在o 的析构函数thread.join() 处。

我已经用clang测试了这个,没有问题。这似乎只发生在 VC11 中。这是为什么?

【问题讨论】:

我看不出代码有什么问题。一种可能性是您在 VC11 处理静态初始化程序中的线程生成时发现了一个错误,这似乎是一个可能存在错误的边缘情况。另一个是您在 ConcurrentQueue 中有一个错误,您没有显示。 静态对象什么时候会被删除? dauphic:在我看来是正确的:设置原子标志,推送一条记录以确保在设置标志后至少唤醒一次,然后等待不可避免的线程退出。 是的。我误读了代码,并认为由于某种原因连接发生在main。看起来不错。 @AndyRoss 我用 TBB 的 tbb::concurrent_bounded_queue 替换了我的 ConcurrentQueue,但问题仍然存在。 【参考方案1】:

最近有一个帖子遇到同样的问题,但我找不到了。

基本上,当您有一个静态生命周期对象试图在其析构函数中结束线程时,VS 的运行时库中会出现死锁。

【讨论】:

在析构函数工作之前加入......似乎是一个临时工作,直到他们修复它。谢谢

以上是关于函数静态变量析构函数和线程的主要内容,如果未能解决你的问题,请参考以下文章

当变量仍然存在时调用 C++ 析构函数

析构函数私有类方法;继承;环境部署;多线程多进程;锁

27)构造和析构函数

静态分配的构造函数和析构函数顺序

静态对象成员会在所属类的析构函数被调用时自动析构吗?

c++类中 各种成员的生命周期?