如何匿名声明std :: thread?

时间:2014-01-17 23:31:00

标签: c++ multithreading c++11 stdthread

考虑以下简短程序:

#include <thread>

int Foo() {
while (1);
}

int main(){
    std::thread t(Foo);
    std::thread s(Foo);

    // (std::thread(Foo));

    t.join();
}

使用

编译并运行(永久)
g++ -Wl,--no-as-needed DoubleBufferTest.cc -o DoubleBufferTest -std=c++0x -pthread

在注释掉的行中,我试图使用here描述的技术匿名声明一个新线程。但是,当该行被注释回来时,我可以编译但运行时会出现以下错误:

terminate called without an active exception            
Aborted (core dumped)                                   

如何正确地匿名声明线程?

注意,我在g++ 4.4.7

3 个答案:

答案 0 :(得分:12)

如果线程尚未加入或分离,

std::thread的析构函数将调用std::terminate

很遗憾,您无法创建这样的匿名线程对象 - 您需要引用thread对象才能调用join()detach()

Scott Meyers在Going Native 2013上发表演讲,他创建了一个包含线程的RAII类,并在析构函数中调用join。你可以做类似的事情:

class ThreadRAII {
public:
  ThreadRAII(std::thread&& thread): t(std::move(thread)) {}
  ~ThreadRAII() { if (t.joinable()) { t.join(); }

private:
  std::thread t;
};

有关详细信息,请参阅他的blog posttalk

你可以像这样使用它

(ThreadRAII(std::thread(Foo)));

但是,你想以这种方式创建一个线程的唯一原因是你不关心它何时(或如果)结束,所以在这种情况下,join没有多大意义。您应该修改析构函数以分离:

~ThreadRAII() { if (t.joinable()) { t.detach(); }

正如评论中所建议的那样,通过完美转发到构建中的内部线程,您可以更容易地使用它:

class ThreadRAII2 {
public:    

    template <typename Func, typename ...Args>
    explicit ThreadRAII2(Func&& func, Args&&... args) :
        t(func, std::forward<Args>(args)...) {  }

    ~ThreadRAII2() { 
        if (t.joinable()) t.detach(); 
    }
private:
    std::thread t;
};

然后你可以像你原来想的那样使用它,不需要分离:

(ThreadRAII2(Foo));

或者,如果Foo接受参数(例如Foo(int)):

(ThreadRAII2(Foo, 42));

答案 1 :(得分:11)

你可以这样做:

std::thread(Foo).detach();

答案 2 :(得分:4)

我不认为这是(你所指的技术)可以用线程。

看看这里;

  

30.3.1.3 thread destructor [thread.thread.destr]

     

〜螺纹();

     

如果joinable()则终止(),否则没有效果。 [注意:要么隐式   在析构函数中分离或连接joinable()线程可能会导致   难以调试正确性(用于分离)或性能(用于连接)错误   仅在引发异常时遇到。因此程序员必须确保   在线程仍可连接时,析构函数永远不会被执行。    - 结束说明]

基本上,当执行继续执行违反上述规则的下一行时,您正在创建的临时匿名对象(即线程)将被销毁。