【问题标题】: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,但问题仍然存在。

标签: c++ multithreading visual-c++ c++11


【解决方案1】:

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

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

【讨论】:

  • 在析构函数工作之前加入......似乎是一个临时工作,直到他们修复它。谢谢
猜你喜欢
  • 1970-01-01
  • 2021-08-19
  • 1970-01-01
  • 2020-07-15
  • 2015-12-27
  • 2014-08-27
  • 1970-01-01
  • 2011-05-20
相关资源
最近更新 更多