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

时间:2016-06-05 20:01:19

标签: c++ multithreading c++14

我想创建一个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的析构函数是否知道这样做是安全的。

3 个答案:

答案 0 :(得分:3)

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

答案 1 :(得分:3)

你可以把std::thread放在任何你想要的地方,它们并不特别。销毁线程句柄是有问题的。您可以隐式分离,隐式删除或隐式连接,并且每个选项都很糟糕。 std::~thread(通常)just kills the whole program。为了防止它joindetach 由于您似乎想要隐式加入,您可能希望使用std::async(可能使用std::launch::async policy)来启动您的线程。它返回一个std::future的析构函数隐式连接。

答案 2 :(得分:1)

根据cppreference.com

  

线程对象没有关联的线程(并且安全   在

之后      
      
  • 是默认构造的
  •   
  • 它已从
  • 移出   
  • join()被称为
  •   
  • 分离()已被称为
  •   

因此,如果您将线程定义为成员变量并按如下方式编写析构函数:

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

一切都很好,因为标准保证std::thread析构函数只能在my_class析构函数see this Q/A之后调用。