线程启动,结束,创建线程的用法

线程运行的开始与结束

线程开始

程序运行起来,生成一个进程,该进程所属的主线程也开始运行。

主线程从main()返回,整个进程也执行完毕,我们自己创建的其他线程,也需要从一个函数开始执行(初始函数),当这个函数执行完毕时,这个线程也将结束。

整个进程执行完毕的标志是主线程执行完毕,此时如果有子线程还未执行完毕,将会被os强制中断(一般情况),换句话说,要保持子线程的状态,要保持主线程的运行(一般情况)

创建一个线程

  • 包含一个头文件#include<thread>
  • 自己创建一个函数
  • main中开始写代码
#include<iostream>
#include<thread>
using namespace std;
void myprint(){
cout << "My thread begin" << endl;
cout << "My thread end" << endl;
}
int main(){
thread myobj(myprint); // myprint可调用对象,创建一个线程,线程入口是my print,并线程开始执行
//加入一个新的分支
myobj.join(); //主线程等待在这里,等待子线程执行完毕
cout << "Main thread begin...." << endl;
return 0;
}

threadc++标准库类

join()阻塞主线程,让主线程等待子线程执行完毕,然后主线程和子线程汇合,主线程继续向下。

如果主线程先于子线程结束,这样的程序是不合格的。

一些例外:

detach()主线程不与子线程汇合,各自执行各自的。引入detach的意义,让主线程逐个等待的编程策略不是很好。一旦detach之后,与主线程关联的对象就会失去与主线程的关联。子线程被后台接管(运行库),当子线程结束之后,被运行时库清理。(守护线程)。一旦调用detach()之后,不能再调用join

joinable()判断是否可以成功使用join()detach()

其他创建线程的方法

用类创建一个该类的可调用对象。

class Ta{
public:
void operator()(){ //不带参数
//.....
}
}

Ta a;
thread myobj(a);
myobj.join();

一旦主线程结束,其中的引用等变量也会被回收,此时如果子线程还未结束,那么会产生不可预料的结果。

Tips:

线程中使用的主线程的对象是复制过去的,一旦主线程结束,原对象会被销毁,复制的对象仍然存在。

用lambda表达式创建

auto mythread = []{
//....
};
thread myobj(mythread);
myobj.join();

互斥量

为了保护共享数据,在操作时,用代码将共享数据锁住再操作数据,做错完数据以后