使用和连接来自不同线程的std :: thread对象

时间:2016-10-10 18:43:16

标签: c++ c++11 stdthread

这是一个基于代码的最小示例:

// Example program
#include <iostream>
#include <string>
#include <thread>


int main()
{
  std::cout << "Start main\n";
  int i = 0;
  auto some_thread = std::thread([&]() { 
     std::cout << "Start some thread\n";
      while(i++ < 100) {
        std::cout << i << std::endl;
        std::this_thread::sleep_for(std::chrono::milliseconds(1000));
      }
  });
  std::this_thread::sleep_for(std::chrono::milliseconds(1000));  

  auto some_thread2 = std::thread([&]() { 
      std::cout << "Start thread 2\n";
      if (some_thread.joinable()) {
        std::cout << "Thread 2 will join\n";
        some_thread.join();
        std::cout << "Thread 2 ended\n";
      } else {
        std::cout << "Thread 2 ended but didn't join\n";
      }
  });
  std::this_thread::sleep_for(std::chrono::milliseconds(1000));
  if (some_thread.joinable()) {
    std::cout << "Main will join\n";
    some_thread.join();
    std::cout << "Main ended\n";
    return 0;
  } else {
    std::cout << "Main ended but didn't join\n";
    return 1;
  }
}

简而言之,完整程序(如本例所示)从不同的线程访问某些std::thread对象,并尝试joindetach

我知道这是一个糟糕的设计,并且如果你尝试加入一个线程两次它会崩溃,因为在第一个完成之后,那么没有与之关联的线程。但事实并非如此。

在此示例中,它在线程结束之前崩溃并且使用Abort trap:6。它只打印几个数字然后崩溃(线程不会结束它的执行)。

代码不是我的,我不想重新设计。我只想了解它为什么会崩溃。

最后一点,原始代码以某种方式使用信号量等工作(虽然有一些随机崩溃)。

2 个答案:

答案 0 :(得分:0)

  

我知道......如果你尝试加入一个线程两次,它会崩溃,因为在第一个完成之后,就没有与之关联的线程了。但事实并非如此。

恰恰相反,这正是这里发生的事情。 some_thread2调用some_thread.join(),当等待some_thread退出时,主线程也在调用some_thread.join()some_thread仍处于活动状态,并且在两次检查时尚未加入,因此joinable()在两种情况下均返回true。

避免崩溃的一种方法是在主线程中检查some_thread2.join();之前添加some_thread.joinable()(但如果这样做,主线程就不需要加入some_thread })。

在任何情况下,都不清楚为什么要从两个不同的线程join线程,所以很难建议更好的解决方案。

答案 1 :(得分:0)

std :: thread库通常在支持pthreads的环境中的pthreads之上实现(例如:libstdc ++)。

引自pthread_join linux documentation

  

如果多个线程同时尝试使用同一个线程加入,   结果未定义。

它还提到它返回以下错误:

  

EINVAL另一个线程已经在等待加入此线程。