C++多线程框架
Thread线程框架
线程定义:
线程可以理解为一个特立独行的函数。其存在的意义,就是并行,避免了主线程的阻塞。
----------------------------thread与函数----------------------------------
线程启动
C++线程的启动, 只需要#include <thread>即可。 线程对象的创建, 意味着线程的开始。
1)同步
#include <iostream>
#include <thread>
#include <unistd.h>
using namespace std;
void func()
{
cout<<"thread id:"<<this_thread::get_id()<<endl;
cout<<"do some work"<<endl;
sleep(3);
}
int main()
{
cout<<"maint thread id:"<<this_thread::get_id()<<endl;
thread t(func);
t.join();
return 0;
}
t.join 和 t.detach 标志着, 线程对象和线程的关系。 t.join 表示, 线程与线程对象的同步关系。 而 t.detach 表示, 线程与线程对象的异步关系。 在线程生成后,必须指定join或者detach状态来。
detach 后的线程,不能再 join,是否可以 join 可以通过 joinable 来判断。
2)异步
#include <iostream>
#include <memory>
using namespace std;
void func()
{
cout<<"thread id:"<<this_thread::get_id()<<endl;
int i = 0;
while(i++<5)
{
cout<<"assist thread running times:"<<i<<endl;
sleep(1);
}
cout<<"----end assist thread work!------"<<endl;
}
int main()
{
cout<<"maint thread id:"<<this_thread::get_id()<<endl;
thread t(func);
// t.join(); //!同步
t.detach(); //!异步
int i =0;
while(i++<10)
{
cout<<"main thread running times:"<<i<<endl;
sleep(1);
}
cout<<"-----main thread finished!-----"<<endl;
}
在次线程detach的状态下,要保证主线程的上声明周期要比次线程声明周期长,否则此线线程将中断退出。
传参方式
线程有自己独立的栈。可供享受全局的变量。在线程启动的时候可以传入启动的参数。
#include <iostream>
#include <thread>
using namespace std;
void func(int n, string s)
{
for(int i=0;i <n ;i++)
{
cout<<s<<endl;
}
}
int main()
{
thread t(func,5,"china");
t.join();
return 0;
}
除了传入参数,共享全局以外,还可以使用std::ref辅助传入本地变量的引用。thread认为不加std::ref包装的变量都是以拷贝的方式传入线程中去的。
#include <iostream>
#include <thread>
using namespace std;
void func(int &n, string &s)
{
for(int i=0;i <n ;i++)
{
cout<<s<<endl;
}
n = 10;
s = "america";
}
int main()
{
int n = 5;
string s = "china";
// thread t(func,n, s); //!编译不过,thread无法区分传入的参数
thread t(func,ref(n), ref(s)); //!正确的传引用的姿势,应该采用std::ref来对变量包装
t.join();
return 0;
----------------------------thread与类成员函数-----------------------------------
以上都是通过线程来包装普通的函数。类的成员函数该如何引入线程呢?如下:
1)类外使用线程(推荐):
#include <iostream>
#include <thread>
using namespace std;
class ThreadTest
{
public:
ThreadTest()
{
cout<<"ThreadTest():"<<this<<endl;
}
void func()
{
int n = 0;
cout<<"void func(int n):"<<this<<endl;
while(n++<10)
{
cout<<"thread in class runtime:"<<n<<endl;
}
}
~ThreadTest() = default;
};
int main()
{
ThreadTest test;
thread t(&ThreadTest::func,test);
t.join();
cout<<"Pls observe the difference between the two printed addresses!"<<endl;return 0;
}
这个函数执行起来显然没什么错误,但是有一个问题:我们构造时对象的内存地址居然与多线程中执行函数地址不一样,要记住这可是该对象的成员函数啊?我们前面已经提到过,不使用std::ref传入线程的变量默认都是以拷贝的方式传入的。两次地址不一样的原因就是如此!要想将该对象的成员函数加入线程,我们应该使用std::ref或者直接传入对象的指针。
#include <iostream>
#include <thread>
using namespace std;
class ThreadTest
{
public:
ThreadTest()
{
cout<<"ThreadTest():"<<this<<endl;
}
void func()
{
int n = 0;
cout<<"void func(int n):"<<this<<endl;
while(n++<10)
{
cout<<"thread in class runtime:"<<n<<endl;
}
}
~ThreadTest() = default;
};
int main()
{
ThreadTest test;
// thread t(&ThreadTest::func,test); //!对象拷贝
thread t(&ThreadTest::func,std::ref(test)); //!传入引用
// thread t(&ThreadTest::func,&test); //!传入指针;
t.join();
cout<<"Please observe the difference between the two printed addresses!"<<endl;return 0;
}
2)类内使用线程:
#include <iostream>
#include <thread>
using namespace std;
class ThreadInClass
{
public:
ThreadInClass(){cout<<"ThreadInClass():"<<this<<endl;}
~ThreadInClass() = default;
void runThread()
{
thread t(&ThreadInClass::func,this);
t.join();
// t.detach();//使用detach,同样也要保证runThread的生存周期比t要长。
}
void func()
{
int n = 0;
cout<<"void func(int n):"<<this<<endl;
while(n++<10){
cout<<"thread in class runtime:"<<n<<endl;
}
}
};
int main()
{
ThreadInClass tic;
tic.runThread();
}