__thread 关键字
2018-09-17 本文已影响0人
dingjiayi
1. 概述
1.1 __thread是GCC内置的线程局部存储设施。_thread变量每一个线程有一份独立实体,各个线程的值互不干扰。可以用来修饰那些带有全局性且值可能变,但是又不值得用全局变量保护的变量。
1.2 举例说明
__thread int count = 0;
int main()
{
//创建线程A
//创建线程B
//此时A和B线程都有一个实体 count,二者并不相同
}
2. 使用举例
#include <iostream>
#include <pthread.h>
#include <unistd.h>
__thread int i = 0;
void* f1(void* arg)
{
i++;
printf("f1 i address %p val %d\n", &i, i);
}
void* f2(void* arg)
{
i += 2;
printf("f2 i address %p val %d\n", &i, i);
}
int main()
{
pthread_t pid1, pid2;
i += 3;
pthread_create(&pid1, NULL, f1, NULL);
pthread_create(&pid2, NULL, f2, NULL);
pthread_join(pid1, NULL);
pthread_join(pid2, NULL);
printf("main i address %p val %d\n", &i, i);
return 0;
}
结果:
注意,f1 和 f2 中的地址并不相同
3. 使用方式
3.1 主要下面三种
__thread int i;
extern __thread struct state s;
static __thread char *p;
3.2 注意事项
(1) __thread是GCC内置的线程局部存储设施
(2) 只能修饰POD类型(类似整型指针的标量,不带自定义的构造、拷贝、赋值、析构的类型,二进制内容可以任意复制memset,memcpy,且内容可以复原).
(3)不能修饰class类型,因为无法自动调用构造函数和析构函数.
(4)可以用于修饰全局变量,函数内的静态变量,不能修饰函数的局部变量或者class的普通成员变量,且__thread变量值只能初始化为编译器常量.
4. 补充
4.1 利用以下一组函数设置
int pthread_once(pthread_once_t *once_control, void (*init_routine)(void));
int pthread_key_create(pthread_key_t *key, void (*destructor)(void*));
void *pthread_getspecific(pthread_key_t key);
int pthread_setspecific(pthread_key_t key, const void *value);
4.2 C++11 引入了线程存储期 符号: thread_local
5. 参考资料
5.1 https://gcc.gnu.org/onlinedocs/gcc-4.2.4/gcc/Thread_002dLocal.html
5.2 https://www.cnblogs.com/zhangzhang/archive/2013/01/06/2847570.html
5.3 https://zh.cppreference.com/w/cpp/language/storage_duration