赞
踩
std::thread是c++11的特性,提供管理多线程的类。
note: 注意下文中线程和线程对象的区别:线程即通俗意义上的线程,而**线程对象(thread对象)**这里指的是thread类的一个具体实例
thread的常用成员函数
详细说明
thread& operator=(thread&& _Other) _NOEXCEPT
{ // move from _Other
return (_Move_thread(_Other));
}
thread(const thread&) = delete; //删除拷贝构造函数
thread& operator=(const thread&) = delete; //删除了左值引用的赋值操作
所以有如下程序段的问题:
std::thread t1;
std::thread t2;
t1 = t2; //错误:左值的赋值操作已被删除
t1 = std::thread(fun); //正确
所以thread对象获得线程管理权有两种方式:1)通过构造函数;2)通过右值赋值操作。
deach()
操作使线程独立于thread对象执行,调用后线程和该thread对象没有任何关系。通过get_id()
获得线程id = 0(即没有线程)。joinable()
和join()
可以用于在销毁销毁thread对象前,等待线程执行结束,避免主线程退出时,其他线程还在继续执行,并访问主线程的相关数据,而导致程序崩溃。detach()
或者join()
,否则程序会崩溃。崩溃的原因:thread对象析构时会调用如下函数,如果线程对象之前没有调用detach(
)或者join()
方法,析构时会执行terminate()
,导致程序崩溃。thread& _Move_thread(thread& _Other)
{ // move from _Other
if (joinable())
_XSTD terminate(); //崩溃原因:terminate()用于终止程序运行。
_Thr = _Other._Thr;
_Thr_set_null(_Other._Thr);
return (*this);
}
这也符合thread作为线程管理对象的设定,析构时如果线程还在运行就不能被析构,否则其管理职责就失去了意义。
创建线程
#include <iostream> #include <string> #include <thread> #include <windows.h> using namespace std; void fun1(){ while (true) { cout << "run in sub thread!"<<endl; Sleep(100); } } void fun2(const std::string &str) { while (true) { cout << "run in sub thread with para:" << str<<endl; Sleep(100); } } void main() { //通过构造函数创建线程 std::thread t1(fun1); //创建线程,并传入参数 std::thread t2(fun2, "subthread2"); //用lambda表达式创建线程 std::thread t3([]() { while (true) { cout << "run in lambda exp thread" << endl; Sleep(100); } }); t1.detach(); t2.detach(); t3.detach(); system("pause"); }
类中使用thread
经常我们需要在执行某个类的方法时开启一个子线程,如果子线程中使用了对象的成员变量,则需要保证在类对象析构前执行完子线程的内容,否则会报内存访问的错误。可以通过如下方式解决这个问题:
下面的例子中,在类的mfun方法中开启了子线程,线程对象并没马上调用detach()或者join()操作,而是在类析构函数中调用,这样就可以保证等子线程执行结束后再析构类的对象。
class ThreadUser { public: ~ThreadUser(){ if (subThread.joinable()) //等待线程执行完毕在释放thread对象 subThread.join(); } void mfun() { subThread = thread([&]() { for(int i = 0; i < num; i++) cout <<"i"<<endl; }); } private: thread subThread; int num; };
类的成员函数作为线程执行函数
类成员函数可以作为thread的线程函数进行执行,但需要传入类的指针作为参数,方法如下:
class ThreadUser {
public:
void tfun() {
cout << "threadsuser fun" << endl;
}
};
void main() {
thread tr(&ThreadUser::tfun, new ThreadUser()); //用ThreadUser对象的成员函数tfun作为线程函数,&<类名>::<成员函数名> 为获得类的成员函数指针的写法。
system("pause");
}
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。