linux私有数据的好处,Linux线程私有数据

[size=medium]

线程私有数据的使用场景是:某个函数在第一次被调用的时候,分配内存block,在以后每次调用的时候,都是用第一次所分配的内存block,无需再次分配。可以用线程私有数据来存储这个内存block。

在多线程环境下,如果不使用线程私有数据,由于函数只分配了一个block,所以各个线程在block上必然会有竞争。如果每个线程对这个block的使用是相互独立的,比如对errno的设置,就可以使用线程私有变量来避免竞争。

可以把线程私有变量看成是一种类型的数据结构,对于同一个key,不同的线程可以有不同的value。Linux为这种数据结构提供了GET和SET接口,即:[/size]

void *pthread_getspecific(pthread_key_t key);//获取key所对应的线程私有数据

​int pthread_setspecific(pthread_key_t key, const void *value); //设置key所对应的线程私有数据

[size=medium]

一般而言,比如key是全局变量,需要通过pthread_key_create(&key, destructor)初始化key。线程1调用pthread_setspecific(key, value1);设置了key所对应的值value1。这种设置在另外一个线程2是不可见的,即线程2通过pthread_getspecific(key)是获取不到value1的。同样线程2通过pthread_setspecific(key, value2)对线程1也没有任何影响。

总的来说,就是对于同一个pthread_key,每个线程都对value有一个独立的副本,所以避免了竞争。

具体例子如下,例子来源于《The Linux Programming Interface - A Linux and UNIX System Programming Handbook》:[/size]

#include

#include /* Get declaration of strerror() */

#include

static pthread_once_t once = PTHREAD_ONCE_INIT;

static pthread_key_t strerrorKey;

#define MAX_ERROR_LEN 256 /* Maximum length of string in per-thread

buffer returned by strerror() */

/* Free thread-specific data buffer */

static void destructor(void *buf) {

free(buf);

}

/* One-time key creation function */

static void createKey(void) {

int s;

/* Allocate a unique thread-specific data key and save the address

of the destructor for thread-specific data buffers */

e s = pthread_key_create(&strerrorKey, destructor);

if (s != 0)

errExitEN(s, "pthread_key_create");

}

char * strerror(int err) {

int s;

char *buf;

/* Make first caller allocate key for thread-specific data */

r s = pthread_once(&once, createKey);

if (s != 0)

errExitEN(s, "pthread_once");

t buf = pthread_getspecific(strerrorKey);

if (buf == NULL) { /* If first call from this thread, allocate

buffer for thread, and save its location */

y buf = malloc(MAX_ERROR_LEN);

if (buf == NULL)

errExit("malloc");

u s = pthread_setspecific(strerrorKey, buf);

if (s != 0)

errExitEN(s, "pthread_setspecific");

}

if (err < 0 || err >= _sys_nerr || _sys_errlist[err] == NULL) {

snprintf(buf, MAX_ERROR_LEN, "Unknown error %d", err);

} else {

strncpy(buf, _sys_errlist[err], MAX_ERROR_LEN - 1);

buf[MAX_ERROR_LEN - 1] = '\0'; /* Ensure null termination */

}

return buf;

}

[size=medium]

thread local和线程私有数据在概念上差不多,thread local为线程私有数据提供了更方便的访问接口。

如下例子[/size]

static __thread char local_buf[MAX_ERROR_LEN];

[size=medium]

定义static变量local_buf,通过__thread修饰,则每个线程都对local_buf,都会有一个独立的副本,它们自己不会相互干扰

通过如下程序的输出,我们可以看到,不同的线程local_buf的地址是不同的,所以每个线程可以独立的对buf修改。[/size]

#include

#include

#include

#define MAX_ERROR_LEN 10240

static char normal_buf[MAX_ERROR_LEN];

static __thread char local_buf[MAX_ERROR_LEN];

void * func(void * arg) {

printf("thread %x : local_buf %x\n", pthread_self(), local_buf);

printf("thread %x : normal_buf %x\n", pthread_self(), normal_buf);

}

int main() {

pthread_t tid;

pthread_create(&tid, NULL, func, NULL);

func(NULL);

pthread_join(tid, NULL);

return 0;

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值