我对以下代码快照的查询很少。
1)关于pthread_create(),假设Thread_1创建了Thread_2。据我了解,Thread_1可以不加入而退出,但是Thread_2仍将继续运行。如下面的示例中没有join()的示例,我无法运行线程,并且看到异常。
2)在少数示例中,我看到没有线程对象的线程创建如下。但是当我这样做时,代码就会终止。
std::thread(&Task::executeThread, this);
I am compiling with below command.
g++ filename.cpp -std=c++11 -lpthread
但是它仍然以异常终止。这是创建线程的正确方法还是C ++的任何其他版本(在我的项目中,他们已经在编译但不确定版本)。
3)在我的项目代码的一些示例中,我看到了以下创建线程的方法。但是我无法执行以下示例。
std::thread( std::bind(&Task::executeThread, this) );
下面是我的代码快照。
#include <iostream>
#include <thread>
class Task
{
public:
void executeThread(void)
{
for(int i = 0; i < 5; i++)
{
std::cout << " :: " << i << std::endl;
}
}
void startThread(void);
};
void Task::startThread(void)
{
std::cout << "\nthis: " << this << std::endl;
#if 1
std::thread th(&Task::executeThread, this);
th.join(); // Without this join() or while(1) loop, thread will terminate
//while(1);
#elif 0
std::thread(&Task::executeThread, this); // Thread creation without thread object
#else
std::thread( std::bind(&Task::executeThread, this) );
while(1);
#endif
}
int main()
{
Task* taskPtr = new Task();
std::cout << "\ntaskPtr: " << taskPtr << std::endl;
taskPtr->startThread();
delete taskPtr;
return 0;
}
感谢与问候
毗湿奴比玛
答案 0 :(得分:5)
std::thread(&Task::executeThread, this);
语句创建并销毁线程对象。当线程未加入或未断开时(例如您的语句中),destructor of std::thread
会调用std::terminate
。
在C ++ 11中没有充分的理由使用std::bind
,因为在空间和速度方面,lambda更好。
构建多线程代码时,在编译和链接时都需要指定-pthread
选项。链接器选项-lpthread
既不合适又不必要。
答案 1 :(得分:4)
根据设计,您需要加入所有产生的线程,或者分离它们。参见例如SO question on join/detach
请注意重要的警告if main() exits while detached threads are still running
我也100%同意另一个答案中关于首选lambda绑定的评论。
最后,请不要对C ++中的线程执行pthread_cancel的诱惑。参见例如pthread_cancel considered harmful
答案 2 :(得分:1)
在C ++中,对象具有生存期。这与在C中处理句柄有些不同。在C ++中,如果在一个作用域中的堆栈上创建对象,则退出该作用域将被销毁。这些规则有一些例外,例如std::move
,但根据经验,您拥有对象的生命周期。
这与上述相同。当您调用std::thread(&Task::executeThread, this);
时,您实际上是在调用线程构造函数。这是线程寿命和对象寿命的开始。请注意,您在堆栈上创建了此对象。如果您离开范围{ .. yourcode .. }
,则将调用DTor。由于您是在std::move
,join
或detatch
之前完成此操作的,因此调用std::terminate()
会引发异常。
相关文档:
我个人建议理解C ++中对象的生存期。简而言之,所有对象都在调用其构造函数时开始其生命周期。当它们被杀死(如超出范围)时,将调用其析构函数。编译器会为您处理此问题,因此,如果您来自C,它是一个新概念。
答案 3 :(得分:0)
谢谢大家的投入。我错过了线程对象作为线程创建的一部分。由于进行了编译,因此出现了异常。下面是我的更新代码。这三种情况都可以正常工作。
cc1