关于__thread和__type__(var)两个gcc扩展

转载自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

好吧,你也看到了,我这里稍微要提一下这个关键字应该注意的一些地方:

  1. __threadGCC内置的线程局部存储设施,存取效率可以和全局变量相比。
  2. __thread变量每一个线程有一份独立实体,各个线程的值互不干扰。可以用来修饰那些带有全局性且值可能变,但是又不值得用全局变量保护的变量。

__thread使用规则:

  1. 只能修饰POD类型(类似整型指针的标量,不带自定义的构造、拷贝、赋值、析构的类型,二进制内容可以任意复制memset,memcpy,且内容可以复原).
  2. 不能修饰class类型,因为无法自动调用构造函数和析构函数.
  3. 可以用于修饰全局变量,函数内的静态变量,不能修饰函数的局部变量或者class的普通成员变量,且__thread变量值只能初始化为编译器常量(值在编译器就可以确定const int i=5,运行期常量是运行初始化后不再改变const int i=rand()).

我们继续来看__typeof__(var).
__typeof__(var)gccC语言的一个扩展保留字,用于声明变量类型,var可以是数据类型(intchar*..),也可以是变量表达式。用起来很爽,不信,你看下面的这个例子。

#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.

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,293评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,604评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,958评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,729评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,719评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,630评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,000评论 3 397
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,665评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,909评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,646评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,726评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,400评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,986评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,959评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,197评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,996评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,481评论 2 342

推荐阅读更多精彩内容