C++(11):线程局部变量thread_local

多线程中,每个线程都拥有自己的栈空间,但是对于全局变量、静态变量以及堆上空间,是共享于多个线程间的,这可以有效的在多个线程间共享数据,但也是多线程竞争的主要来源:

#include <iostream>
#include <thread>
using namespace std;

int g_d{0};

void tFunc(int a)
{
	for(int i = 0; i < a; ++i)
	{
		g_d++;
	}
	cout<<"thread:"<<a<<" g_d="<<g_d<<endl;
}

int main(){
	thread t1(tFunc, 60000);
	thread t2(tFunc, 80000);
	t1.join();
	t2.join();
	return 0;
}

两个线程分别对全局变量g_d进行操作,产生竞争
运行程序输出:
thread:60000 g_d=80419
thread:80000 g_d=98365

由于产生了线程竞争,因此此结果为随机的 

即使通过原子类型,也无法保证程序的运行结果:

#include <iostream>
#include <atomic>
#include <thread>
using namespace std;

atomic_int g_d{0};

void tFunc(int a)
{
	for(int i = 0; i < a; ++i)
	{
		g_d++;
	}
	cout<<"thread:"<<a<<" g_d="<<g_d<<endl;
}

int main(){
	thread t1(tFunc, 60000);
	thread t2(tFunc, 80000);
	t1.join();
	t2.join();
	return 0;
}

运行程序输出:
thread:60000 g_d=119472(此结果为随机的)
thread:80000 g_d=140000


虽然原子类型可以避免竞争,但是不能避免对全局变量的共享
因此只能保证当t1和t2线程运行结束后,g_d的值一定是140000
但无法保证每个线程的在运行期间g_d的值,因此会出现thread:60000 g_d=119472这种随机情况

C++11引入了线程局部变量,即通过声明变量时加入修饰符thread_local,可以将变量声明为每个线程都有一份专属的变量,因此多个线程间虽然表面上看起来操作的是同一变量名,但实际上是操作的线程专属变量,不会造成运行时干扰:

#include <iostream>
#include <thread>
using namespace std;

thread_local int g_d{0};    //每个线程都有一个专属于自己的全局变量

void tFunc(int a)
{
	for(int i = 0; i < a; ++i)
	{
		g_d++;
	}
	cout<<"thread:"<<a<<" g_d="<<g_d<<endl;
}

int main(){
	thread t1(tFunc, 60000);
	thread t2(tFunc, 80000);
	t1.join();
	t2.join();
	return 0;
}

运行程度输出:
thread:60000 g_d=60000
thread:80000 g_d=80000

需要指出的是,thread_local可以定义如下几种类型的变量:

(1).命名空间(全局)变量;

(2).文件静态变量;

(3).函数静态变量;

(4).静态成员变量(成员变量必须是static的,此时对于同一个线程内的该类的多个对象,会共享这一个静态变量实例)。 


版权声明:本文为jiemashizhen原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。