【问题标题】:When std::thread is destructed and what happen to the shared_ptr if the pointer point to it?当 std::thread 被破坏时,如果指针指向它,shared_ptr 会发生什么?
【发布时间】:2017-06-12 17:32:26
【问题描述】:

当我创建一个 std::thread 实例时,它什么时候会被销毁?线程完成任务的时间是被销毁还是作为普通对象工作,当它不再使用时将被销毁?

//a fake function for std::thread
void func();
void main()
{
    auto threadPtr = std::make_shared<std::thread>(func)
    threadPtr->join(); 
    // is thread object which threadPtr point destructed in here ? 
    //... other stuffs ....    
}

threadPtr-&gt;join()之后线程对象是否被破坏?

【问题讨论】:

  • 没有其他代码共享该线程实例,所以如果它只是在堆栈上分配,它只是一样的。
  • 你认为线程对象为什么被破坏了?
  • threadPtr 在您离开 main 时被销毁,就像任何其他堆栈变量一样。
  • 所以 std::thread 对象将被销毁为普通对象。它完成任务后不会被破坏,对吗?
  • @buddha “它完成任务不会被破坏,对吗?” 没错!

标签: c++ multithreading shared-ptr stdthread


【解决方案1】:

threadPtr-&gt;join()之后线程对象是否被破坏?

没有。 join() 结束std::thread 对象所代表的执行线程,它不会破坏std::thread 对象。

当我创建一个 std::thread 实例时,它什么时候会被销毁?

threadPtr 超出范围时它将被销毁,因为它是一个自动对象(它有automatic storage duration)。 std::shared_ptr 析构函数会调用std::thread 析构函数,然后释放它获得的内存。

【讨论】:

    【解决方案2】:

    底层操作系统线程可能已经终止,但这与被破坏的 C++ std::thread 对象不同。

    执行以下操作:

    #include <iostream>
    #include <thread>
    #include <mutex>
    #include <atomic>
    
    std::mutex cout_mutex;
    std::atomic<bool> waiter{true};
    
    void func(){
        {
            std::lock_guard<std::mutex> guard(cout_mutex);
            std::cout << "funky\n";
        }
        while(waiter);//cheap spin waiting...
    }
    
    int main() {
    
        auto threadPtr = std::make_shared<std::thread>(func);
        {
            std::lock_guard<std::mutex> guard(cout_mutex);
            std::cout << "an active thread id: "<<threadPtr->get_id()<<'\n';
        }
        waiter=false;
        threadPtr->join();
        std::cout << "terminated thread id: "<< threadPtr->get_id()<<'\n';
        return 0;
    }
    

    输出不同,但这里可能的输出是:

    an active thread id: 47441922455296
    funky
    terminated thread id: thread::id of a non-executing thread
    

    threadptr 中包含的对象在销毁之前一直有效,但可能正在引用已终止的线程。

    std::thread 通常是包装类(或代理设计模式)的实现。它包含一个(可能是空的)对通常是操作系统线程对象的引用。当被包裹的线程结束时,引用可能为空。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-03-06
      • 1970-01-01
      • 2015-11-17
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多