线程安全、C++多线程的管理(detach、join、get_id)

线程安全

线程安全函数:当一个函数被多个并发线程反复调用的时候,它的结果始终是正确的

一般线程不安全的情况,是由于同一个进程的不同线程共享进程内存空间中的全局/静态存储区和堆,如果一个函数中包含全局变量和静态变量,那么可能会线程不安全,导致程序错误。但是如果对全局变量和静态变量的操作只有读,没有修改的话,也可以将这个函数看做是线程安全的。


C++多线程(C++11)

多线程demo

C++11的标准库,提供了多线程库,需要 #include 头文件(主要提供对线程管理的类std::thread

#include 
#include 
using namespace std;

void output(int i){
	cout << i << endl;
}

int main(){
	for(uint8_t i = 0; i < 8; i++)	{
		thread th(output, i);
		th.detach();	//detach表示该线程可以在后台运行,无需等待当前线程完成,会继续执行后面的操作
	}
	getchar();
	
	return 0;
}

输出结果:
线程安全、C++多线程的管理(detach、join、get_id)_第1张图片
输出的结果与预期有较大的差别。

分析:

创建了8个进程,每个进程都会调用output方法,output的过程分两步:①打印出i的值、②打印换行

涉及到多线程最核心的问题:资源竞争

8核CPU创建了8个线程,但是控制台只有1个,并且在同一时刻只能有一个线程占有这个唯一的控制台。

所以会出现情况:在一个线程占用控制台打印数字之后,没来得及打印换行,控制台就被另一个进程占用的情况。

C++11中的两种等待线程结束的方式:

detach方式,启动的线程自主在后台运行,当前的代码继续往下执行,不用等待进程结束。创建的新进程同时并发执行。
join方式会阻塞当前的代码,需要等待当前启动的线程执行完成,才会继续进行下一步。

使用join方式修改之前的demo

#include 
#include 
#include 
using namespace std;

void output(int i){
	cout << i << endl;
}

int main(){
	stringstream ss;
	for(int i = 0; i < 8; i++)	{
		thread th(output, i);
		ss << "(" << th.get_id() << "): ";	//通过get_id获取线程的id 
		cout << ss.str();
		ss.str("");	//释放ss的缓冲区 
		th.join();
	}
	
	return 0;
}

//用thread的实例调用get_id()来获取线程的标识

运行结果如下:
线程安全、C++多线程的管理(detach、join、get_id)_第2张图片

通过使用join,阻塞的方式来使当前线程执行完毕后,下一个线程再开始执行。

你可能感兴趣的:(C++,计算机系统)