C++11Linux多线程编程

__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

上一篇下一篇

猜你喜欢

热点阅读