轉(zhuǎn)載自http://blog.csdn.net/jfkidear/article/details/7990540
本文修正了很多錯(cuò)誤,然后加入了一些補(bǔ)充信息。
__thread是一個(gè)非常有用的關(guān)鍵子,在多線程編程中,如果使用__thread關(guān)鍵字修飾global變量,可以使得這個(gè)變量在每個(gè)線程都私有一份。
下面是一個(gè)例子:
#include <iostream>
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
#include <assert.h>
static __thread int count; // 一般來(lái)說(shuō),這個(gè)玩意在每個(gè)線程里面都會(huì)存在一份
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); // 啟動(dòng)一個(gè)線程運(yùn)行function1
assert(ret == 0);
ret = pthread_create(thread_id + 1, NULL, function2, NULL); // 啟動(dòng)另外一個(gè)線程運(yùn)行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;
}
輸出的結(jié)果如下:
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
好吧,你也看到了,我這里稍微要提一下這個(gè)關(guān)鍵字應(yīng)該注意的一些地方:
-
__thread是GCC內(nèi)置的線程局部存儲(chǔ)設(shè)施,存取效率可以和全局變量相比。 -
__thread變量每一個(gè)線程有一份獨(dú)立實(shí)體,各個(gè)線程的值互不干擾??梢杂脕?lái)修飾那些帶有全局性且值可能變,但是又不值得用全局變量保護(hù)的變量。
__thread使用規(guī)則:
- 只能修飾
POD類型(類似整型指針的標(biāo)量,不帶自定義的構(gòu)造、拷貝、賦值、析構(gòu)的類型,二進(jìn)制內(nèi)容可以任意復(fù)制memset,memcpy,且內(nèi)容可以復(fù)原). - 不能修飾
class類型,因?yàn)闊o(wú)法自動(dòng)調(diào)用構(gòu)造函數(shù)和析構(gòu)函數(shù). - 可以用于修飾全局變量,函數(shù)內(nèi)的靜態(tài)變量,不能修飾函數(shù)的局部變量或者
class的普通成員變量,且__thread變量值只能初始化為編譯器常量(值在編譯器就可以確定const int i=5,運(yùn)行期常量是運(yùn)行初始化后不再改變const int i=rand()).
我們繼續(xù)來(lái)看__typeof__(var).
__typeof__(var) 是gcc對(duì)C語(yǔ)言的一個(gè)擴(kuò)展保留字,用于聲明變量類型,var可以是數(shù)據(jù)類型(int, char*..),也可以是變量表達(dá)式。用起來(lái)很爽,不信,你看下面的這個(gè)例子。
#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;
}
輸出的結(jié)果是10.