多线程中,每个线程都拥有自己的栈空间,但是对于全局变量、静态变量以及堆上空间,是共享于多个线程间的,这可以有效的在多个线程间共享数据,但也是多线程竞争的主要来源:
#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版权协议,转载请附上原文出处链接和本声明。