如何在C++智能指针中放置线程

How do I put a thread in a C++ smart pointer?

本文关键字:线程 指针 智能 C++      更新时间:2023-10-16

我想创建一个C++类,线程每分钟做一次工作。

首先,我可以将线程定义为变量成员吗?

class my_class
{
public:
    my_class()
        : my_thread_(task, this)
    {
    }
    ~my_class()
    {
        done_ = true;
    }
    void run()
    {
        while(!done_)
        {
            ...do work in the thread...
        }
    }
private:
    static task(my_class * ptr)
    {
        ptr->run();
    }
    std::thread          my_thread_;
    std::atomic<bool>    done_ = false;
};

其次,我可以改用带有线程的智能指针吗?

class my_class
{
public:
    ~my_class()
    {
        done_ = true;
    }
    void init()
    {
        my_thread_.reset(new std::thread(task, this));
    }
    void run()
    {
        while(!done_)
        {
            ...do work in the thread...
        }
    }
private:
    static task(my_class * ptr)
    {
        ptr->run();
    }
    std::unique_ptr<std::thread>    my_thread_;
    std::atomic<bool>               done_ = false;
};

在我看来,我需要先加入子线程才能销毁它,但我想知道 std::thread 的析构函数是否知道安全地执行此操作。

你可以把std::thread放在任何你想要的地方,它们并不特别。销毁线程句柄是有问题的。你可以隐式分离、隐式终止或隐式加入,每个选项都是不好的。 std::~thread(通常)只是杀死整个程序。防止joindetach它。
由于您似乎想要隐式加入,因此您可能希望使用std::async(可能使用 std::launch::async 策略)来启动线程。它返回一个析构函数隐式联接的std::future

可以

创建std::unique_ptr<std::thread> .它将调用 std::thread 析构函数,当unique_ptr范围结束时。请记住,调用 std::thread 析构函数并不是轻轻地终止运行,而是通过 std::terminate 终止运行。要正常结束 std::thread,您必须在 std::thread 对象上运行.join()

根据 cppreference.com,

线程

对象没有关联的线程(并且可以安全地 销毁)之后

  • 它是默认构造的
  • 它已从
  • join() 已被调用
  • 分离() 已被调用

因此,如果您将线程定义为成员变量并像这样编写析构函数:

~my_class()
{
    done_ = true;
    my_thread_.join();
}

一切都很好,因为标准保证std::thread析构函数只会在my_class析构函数之后调用,请参阅此问答。