posix多线程--线程私有数据

1.当多个线程共享一个变量时,将该变量定义为静态或外部变量,使用互斥量确保共享变量的安全访问。
如果每个线程都需要一个私有变量值,则该值成为线程的私有数据。程序创建一个键,每个线程独立地设定或得到自己的键值,各线程间私有数据互不影响。

2.建立线程私有数据
int pthread_key_create(pthread_key_t *key,void (*destructor)(void *));
int pthread_key_delete(pthread_key_t key);
int pthread_setspecific(pthread_key_t key,void *value);
void *pthread_getspecific(pthread_key_t key);

私有数据键,若多次创建,会覆盖掉前面创建的键,对应的键值也将永远丢失。

使用pthread_key_delete释放一个私有数据键时,必须保证所有线程都不在持有该键的值。
更好的做法是不释放线程私有数据键,因为线程私有数据键最多可达128个,很少有程序需要这么多的树木,没有必要手动释放。

代码示例如下:
创建数据键,设置键值,获取键值

#include<stdio.h>
#include<pthread.h>
typedef struct tsd_tag
{
        pthread_t tid;
        char *string;
}tsd_t;
pthread_key_t tsd_key;
pthread_once_t key_once = PTHREAD_ONCE_INIT;
void one_routine(void)
{
        pthread_key_create(&tsd_key,NULL);;
}
void *thread_routine(void *arg)
{
        pthread_once(&key_once,one_routine);
        tsd_t *value;
        value = (tsd_t*)malloc(sizeof(tsd_t));
        pthread_setspecific(tsd_key,value);
        value->tid = pthread_self();
        value->string = (char*)arg;
        value=(tsd_t*)pthread_getspecific(tsd_key);
        sleep(2);
        value=(tsd_t*)pthread_getspecific(tsd_key);
        printf("%s done...\n",value->string);
}
int main(void)
{
        pthread_t tid1,tid2;
        pthread_create(&tid1,NULL,thread_routine,"thread 1");
        pthread_create(&tid2,NULL,thread_routine,"thread 2");
        pthread_exit(NULL);
}         

3.destructor函数
destructor函数仅仅当线程终止时被调用。当线程终止时,pthreads调用键的destructor函数前,将线程私有数据置为NULL,所以若线程私有数据值是堆存储的地址,并且想在destructor函数中释放,必须使用传递给destructor的参数,而不是pthread_getspecific的参数。可以自定义destructor函数。

键值为NULL意味着线程对应该键值不再有值,而不是赋空值。否则若随后调用pthread_key_create建立该键,线程将会收到旧值。

线程私有数据键的destructor函数在键值替换的时候不会被调用。即,如果在堆中将一个结构的指针作为键值,又分配一个新结构,并将新结构指针赋给相同数据键,则指向旧结构的指针不会调用destructor函数。

代码示例如下:

三个线程的私有变量数据,自定义destructor函数,在线程结束后,释放堆存储,在所有线程结束后,销毁私有数据键。

#include<stdio.h>
#include<pthread.h>
typedef struct private_tag
{
        pthread_t tid;
        char *string;
}private_t;
pthread_key_t key;
pthread_mutex_t mutex=PTHREAD_MUTEX_INITIALIZER;
long counter = 0;
void key_destructor(void *value)
{
        private_t *private = (private_t*)value;
        printf("thread \"%s\" exiting...\n",private->string);
        free(value);
        pthread_mutex_lock(&mutex);
        counter--;
        if(counter<=0)
        {
                pthread_key_delete(key);
                printf("key deleted...\n");
        }
        pthread_mutex_unlock(&mutex);
}
void *key_get(void)
{
        void *value;
        value = pthread_getspecific(key);
        if(value==NULL)
        {
printf("malloc\n");
value = malloc(sizeof(private_t));
                pthread_setspecific(key,(void*)value);
        }
        return value;
}
void *thread_routine(void *arg)
{
        private_t *value;
        value = (private_t*)key_get();
        value->tid = pthread_self();
        value->string = (char*)arg;
        printf("thread \"%s\" starting...\n",value->string);
        sleep(2);
        return NULL;
}
int main(void)
{
        pthread_t tid1,tid2;
        private_t *value;
        pthread_key_create(&key,key_destructor);
        counter = 3;
        value = (private_t *)key_get();
        value->tid = pthread_self();
        value->string = "Main thread";
        pthread_create(&tid1,NULL,thread_routine,"Thread 1");
        pthread_create(&tid2,NULL,thread_routine,"Thread 2");
        printf("exiting\n");
        pthread_exit(NULL);
}                        

时间: 2024-07-28 17:34:22

posix多线程--线程私有数据的相关文章

【C/C++多线程编程之十】pthread线程私有数据

多线程编程之线程私有数据 Pthread是 POSIX threads 的简称,是POSIX的线程标准.  线程同步从互斥量[C/C++多线程编程之六]pthread互斥量,信号量[C/C++多线程编程之七]pthread信号量,条件变量[C/C++多线程编程之八]pthread条件变量,读写锁[C/C++多线程编程之九]pthread读写锁,多线程的同步机制已经有了清晰深入的探究,多线程编程的精髓所在,需要深入理解.        线程私有数据TSD(Thread-specific Data)

线程私有数据

在多线程程序中,经常要用全局变量来实现多个函数间的数据共享.由于数据空间是共享的,因此全局变量也为所有线程共有. 测试代码如下: [cpp] view plaincopy #include <stdio.h> #include <pthread.h> #include <unistd.h> #include <stdlib.h> int key = 100; //全局变量 void *helloworld_one(void *arg) { printf(&q

pthread_getspecific()--读线程私有数据|pthread_setspecific()--写线程私有数据

原型: #include <pthread.h> void *pthread_getspecific(pthread_key_t key); int pthread_setspecific(pthread_key_t key, const void *value); 说明: TSD 的读写都通过上面两个专门的 Posix Thread 函数进行. 函数 pthread_setspecific() 将 pointer 的值 (不是锁指的内容) 与key 相关联. 函数 pthread_getsp

Linux系统编程——线程私有数据

在多线程程序中,经常要用全局变量来实现多个函数间的数据共享.由于数据空间是共享的,因此全局变量也为所有线程共有. 测试代码如下: #include <stdio.h> #include <pthread.h> #include <unistd.h> #include <stdlib.h> int key = 100; //全局变量 void *helloworld_one(void *arg) { printf("the message is %s

12.6 线程私有数据

线程私有数据是一种用于存储和获取与特定线程相关联数据的机制,称为线程特定的或者是线程私有的,是因为我们希望每个线程都可以独立访问其独有的数据,而不用担心与其他线程的同步访问问题. 许多人费力实现了促进进程数据以及属性贡献的线程模型,那么为什么还有人想要实现一个接口,在这样一个模型中防止共享呢?有如下两点原因: 首先,有些时候我们需要以线程为基础维护一些数据,因为没有任何机制可以保证线程ID总是比较小的,且是连续的整数,因此我们不能简单地将每一个线程的私有数据分配为一个数组,然后使用线程ID作为索

SylixOS线程私有数据浅析

目录 1. 线程私有数据概述    1 2. 线程私有数据的相关API函数流程浅析    1 2.1    加入线程私有变量    1 2.2    删除线程私有变量    3 2.3    设置私有线程变量    6 2.4    获得线程私有变量值    8 3. 总结    10 4. 参考文献    10 线程私有数据概述 在SylixOS中为了满足多线程安全的要求,使得一种资源可以安全的被多个线程使用,采用了包括代码临界区保护和可重入性等方法.本文描述实现可重入的一种方法:线程私有数据

线程私有数据和pthread_once

#include <stdio.h> #include <pthread.h> pthread_key_t key; pthread_once_t ponce = PTHREAD_ONCE_INIT; void ronce(){ printf("%s\n", "ronce"); } void *thread1(){ pthread_setspecific(key, "thread1"); printf("%s\n

操作线程私有数据的函数主要有4个:

在线程内部,线程私有数据可以被各个函数访问到,但它对其他线程是屏蔽的. 使用线程数据时,首先要为每个线程数据创建一个相关联的键.在各个线程内部,都使用这个公用的键来指代线程数据,但是在不同的线程中,这个键代表的数据是不同的.也就是说,key一旦被创建,所有线程都可以访问它,但各线程可根据自己的需要往key中填入不同的值.这相当于提供了一个同名而不同值的全局变量,一键多值. 操作线程私有数据的函数主要有4个:pthread_key_create(创建一个键)pthread_setspecific(

POSIX多线程--线程取消

1.三种取消状态Off                   禁用取消Deferred           推迟取消:在下一个取消点执行取消Asynchronous   异步取消:可以随时执行取消 int pthread_cancel(pthread_t thread) 2.推迟取消:在下一个取消点执行取消 Pthreads系统上的某些函数会被作为取消点,如pthread_testcancel,sleep,pthread_cond_wait等.线程调用pthread_cancel函数后,被取消线程