美文网首页
关于__thread和__type__(var)两个gcc扩展

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

作者: Yihulee | 来源:发表于2016-08-30 22:19 被阅读765次

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

    相关文章

      网友评论

          本文标题:关于__thread和__type__(var)两个gcc扩展

          本文链接:https://www.haomeiwen.com/subject/fzkqettx.html