使用 std::thread & std::bind 在成员函数中启动线程

Start thread within member function using std::thread & std::bind

本文关键字:std 函数 线程 成员 启动 bind thread 使用      更新时间:2023-10-16

我对下面的代码快照几乎没有疑问。

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;
}

感谢和问候

毗湿奴比玛

std::thread(&Task::executeThread, this);语句创建并销毁线程对象。std::thread的析构函数在线程未连接或分离时调用std::terminate(如在语句中(。

没有充分的理由在 C++11 中使用std::bind,因为 lambda 在空间和速度方面更好。

构建多线程代码时,需要在编译和链接时指定-pthread选项。链接器选项-lpthread既不充分又不必要。

根据设计,您需要连接您生成的所有线程,或分离它们。例如,请参阅有关连接/分离的 SO 问题

另请参阅 cpp首选项,分离

另请注意,如果 main(( 在分离的线程仍在运行时退出,则需注意重要的注意事项

我也 100% 同意另一个答案中关于更喜欢 lambda 绑定的评论。

最后,不要陷入在C++线程上做pthread_cancel的诱惑。例如,pthread_cancel被认为是有害

  1. 在C++对象有生存期。这与在 C 中处理句柄有点不同。C++,如果您在一个作用域的堆栈上创建一个对象,则退出该作用域时该对象将被销毁。这些规则有一些例外,如std::move,但根据经验,您拥有对象的生命周期。

  2. 这与上述答案相同。当您调用std::thread(&Task::executeThread, this);时,您实际上是在调用线程构造函数。这是线程寿命和对象生存期的开始。请注意,您在堆栈上创建了此对象。如果将作用域{ .. yourcode .. }将调用 DTor。由于您在std::movejoindetatch之前已经这样做了,因此调用std::terminate()引发异常。

  3. 您可以通过这种方式创建线程。如果您查看 std::thread::thread(构造函数(的链接文档,就会发现一个以相同方式创建对象 foo 的示例。您收到哪些错误?

相关文档:

a. std::thread::~thread((

b. 标准::线程::线程

c. C++寿命

我个人建议了解C++中对象的生存期。简而言之,所有对象在调用其构造函数时开始其生存期。当它们被杀死时(如在范围之外(,它们的析构函数被调用。编译器会为您处理此问题,因此,如果您来自 C,这是一个新概念。

谢谢大家的投入。我错过了线程对象作为线程创建的一部分。因此,虽然编译,但我得到了例外。下面是我更新的代码。所有三种方案都工作正常。

#include <iostream>
#include <thread>
class Task
{
public:
void executeThread(std::string command)
{
for(int i = 0; i < 5; i++)
{
std::cout << command << " :: " << i << std::endl;
}
}
void startThread(void);
std::thread th2;
std::thread th3;
};
void Task::startThread(void)
{
std::cout << "nthis: " << this << std::endl;
#if 0
std::thread th1(&Task::executeThread, this, "Thread1");
th1.join(); // Without join(), thread will terminate
#elif 0
th2 = std::thread(&Task::executeThread, this, "Thread2");
th2.join();
#else
th3 = std::thread( std::bind(&Task::executeThread, this, "Thread3") );
th3.join();
#endif
}
int main()
{
Task* taskPtr = new Task();
std::cout << "ntaskPtr: " << taskPtr << std::endl;
taskPtr->startThread();
delete taskPtr;
return 0;
}