转载自http://blog.csdn.net/jfkidear/article/details/7990540
本文修正了很多错误,然后加入了一些补充信息。
__thread
是一个非常有用的关键子,在多线程编程中,如果使用__thread
关键字修饰global
变量,可以使得这个变量在每个线程都私有一份。
下面是一个例子:
#include <iostream>
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
#include <assert.h>
static __thread int count; // 一般来说,这个玩意在每个线程里面都会存在一份
void *function1(void *argc)
{
printf("porgran pid:%u, the function1 pthread id is %lu, count:%d\n", getpid(), pthread_self(), count);
count = 10;
printf("porgran pid:%u, last the function1 pthread id is %lu, count:%d\n", getpid(), pthread_self(), count);
return 0;
}
void *function2(void *argc)
{
printf("porgran pid:%u, the function2 pthread id is %lu, count:%d\n", getpid(), pthread_self(), count);
sleep(2);
count = 100;
printf("porgran pid:%u, last the function2 pthread id is %lu, count:%d\n", getpid(), pthread_self(), count);
return 0;
}
int main()
{
pthread_t thread_id[2];
int ret;
pthread_t main_thread_id;
main_thread_id = pthread_self(); // 主线程的id
count = 2;
printf("porgran pid:%u, main_thread_id:%lu, count:%d\n", getpid(), main_thread_id, count);
ret = pthread_create(thread_id, NULL, function1, NULL); // 启动一个线程运行function1
assert(ret == 0);
ret = pthread_create(thread_id + 1, NULL, function2, NULL); // 启动另外一个线程运行function2
assert(ret == 0);
ret = pthread_join(thread_id[0], NULL); // 等待退出
assert(ret == 0);
ret = pthread_join(thread_id[1], NULL);
assert(ret == 0);
count = 1000;
printf("porgran pid:%u, last main_thread_id:%lu, count:%d\n", getpid(), main_thread_id, count);
return 0;
}
输出的结果如下:
porgran pid:2095, main_thread_id:140737353951040, count:2
porgran pid:2095, the function1 pthread id is 140737337112320, count:0
porgran pid:2095, last the function1 pthread id is 140737337112320, count:10
porgran pid:2095, the function2 pthread id is 140737328719616, count:0
porgran pid:2095, last the function2 pthread id is 140737328719616, count:100
porgran pid:2095, last main_thread_id:140737353951040, count:1000
好吧,你也看到了,我这里稍微要提一下这个关键字应该注意的一些地方:
-
__thread
是GCC
内置的线程局部存储设施,存取效率可以和全局变量相比。 -
__thread
变量每一个线程有一份独立实体,各个线程的值互不干扰。可以用来修饰那些带有全局性且值可能变,但是又不值得用全局变量保护的变量。
__thread
使用规则:
- 只能修饰
POD
类型(类似整型指针的标量,不带自定义的构造、拷贝、赋值、析构的类型,二进制内容可以任意复制memset
,memcpy
,且内容可以复原). - 不能修饰
class
类型,因为无法自动调用构造函数和析构函数. - 可以用于修饰全局变量,函数内的静态变量,不能修饰函数的局部变量或者
class
的普通成员变量,且__thread
变量值只能初始化为编译器常量(值在编译器就可以确定const int i=5
,运行期常量是运行初始化后不再改变const int i=rand()
).
我们继续来看__typeof__(var)
.
__typeof__(var)
是gcc
对C
语言的一个扩展保留字,用于声明变量类型,var
可以是数据类型(int
, char*
..),也可以是变量表达式。用起来很爽,不信,你看下面的这个例子。
#include <iostream>
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
#include <assert.h>
// 下面的##表示连接符
#define DEFINE_MY_TYPE(type, name) __thread __typeof__(type) my_var_ ## name
DEFINE_MY_TYPE(int, one); //It is equivalent to '__thread int my_var_one'; which is a thread variable.
int main()
{
__typeof__(int *) x; //It is equivalent to 'int *x';
__typeof__(int) a;//It is equivalent to 'int a';
__typeof__(*x) y;//It is equivalent to 'int y';
__typeof__(&a) b;//It is equivalent to 'int* b';
__typeof__(__typeof__(int *)[4]) z; //It is equivalent to 'int *z[4]';
//y = *x; // y是int类型的,然后x是int*类型的
x = &a;
b = &a; // a是int类型的,然后b是int *类型的吧!
a = 10;
std::cout << *b << std::endl;
z[0] = x;
z[1] = &a;
return 0;
}
输出的结果是10
.