线程私有数据 - CSDN
精华内容
参与话题
  • linux线程私有数据详解

    千次阅读 2016-08-22 22:15:50
    在单线程程序中,函数经常使用全局变量或静态变量,这是不会影响程序的正确性的,但...而解决这一问题的一种方式就是使用线程私有数据线程私有数据采用了一种被称为一键多值的技术,即一个键对应多个数值。访问数据时都

        在单线程程序中,函数经常使用全局变量或静态变量,这是不会影响程序的正确性的,但如果线程调用的函数使用全局变量或静态变量,则很可能引起编程错误,因为这些函数使用的全局变量和静态变量无法为不同的线程保存各自的值,而当同一进程内的不同线程几乎同时调用这样的函数时就可能会有问题发生。而解决这一问题的一种方式就是使用线程私有数据。线程私有数据采用了一种被称为一键多值的技术,即一个键对应多个数值。访问数据时都是通过键值来访问,好像是对一个变量进行访问,其实是在访问不同的数据。使用线程私有数据时,首先要为每个线程数据创建一个相关联的键。在各个线程内部,都使用这个公用的键来指代线程数据,但是在不同的线程中,这个键代表的数据是不同的。

     根据<<unix环境高级编程>>中所涉及的设计线程私有数据的原因:

    (1).在维护每个线程的私有数据的时候,我们可能会想到分配一个保存线程数据的数组,用线程的ID 作为数组的索引来实现访问,但是有一个问题是系统生成的线程ID不能保证是一个小而连续的整数, 并且用数组实现的时候由于其他线程也可以访问其数组中的数据,这样会 引起数据混乱。
    (2).它提供了让基于进程的接口适应多线程环境的机制.一个很明显的实例就是errno。以前的接口(线程 出现以前)把errno定义为进程上下文中全局可访问的整数。系统调用和库例程在调用或执行失败时设置 errno,把它作为操作失败的附属结果。为了让线程也能够使用那些原本基于进程的系统调用和库例程,errno 被重定义为线程私有数据。这样,一个线程做了重置errno的操作也不会影响进程中其他线程的errno值。

    线程私有数据的几个重要的含有:

    1.int pthread_key_create (pthread_key_t *key, void (*destructor)(void *));
    //第一个参数为指向一个键值的指针,第二个参数指明了一个destructor函数,如果这个参数不为空,那么当每个线程结束时,系统将调用这个函数来释放绑定在这个
    //键上的内存块。
    2.int pthread_key_delete (pthread_key_t key);
    3.int pthread_setspecific (pthread_key_t key, const void *value);
    //其中value就是不同的线程中,key值所关联的私有数据地址,这些地址可以用malloc来分配;
    4.void *pthread_getspecific (pthread_key_t key);
    //获取线程私有数据的地址
    5.int phread_once(pthread_once_t *onceptr, vid(*init)(void));
    注意:pthread_once 使用onceptr 参数指向的变量中的值确保init参数所指的函数在进程范围内之被调用一次,
    onceptr必须是一个非本地变量(即全局变量或者静态变量),而且必须初始化为PTHREAD_ONCE_INIT。
    pthread_key_t key;
    pthread_once_t once = PTHREAD_ONCE_INIT;
    void destructor(void *ptr){
         free(ptr);
    }
    void excute_once(void)  {
        pthread_key_create(&key, destructor);
    
    }
    int main(){
       pthread_once(&r1_once, excute_once);
    }
    

    当我们调用pthread_key_create时,内核从Linux的TSD池中分配一项,将其值赋给key供以后访问使用,它的第一个参数key为指向键值的指针,第二个参数为一个函数指针,如果指针不为空,则在线程退出时将以key所关联的数据为参数调用destr_function(),释放分配的缓冲区。 key一旦被创建,所有线程都可以访问它,但各线程可以根据自己的需要往key中填入不同的值,这就相当于提供了一个同名而不同值的全局变量,一键多值。其中TSD池的结构如下:

    内核支持的pthread_keys是有限的(可能是128也可能),除了进程范围内的Key结构数组之外,系统还在进程内维护了关于多个线程的多条信息。这些特定于线程的信息我们称之为Pthread结构。其中部分内容是我们称之为pkey数组的一个128个元素的指针数组。系统维护的关于每个线程的信息结构图如下:


    一旦我们在某个线程里面调用pthread_setspecific将key与某个空间(这个空间可以是malloc申请的)相关连的时候,上面的结构就变成

    下面我们用一个例子来解释线程的私有结构:

    #include <limits.h>  
    #include <string.h>  
    #include <pthread.h>  
    #include <stdlib.h>  
    #include <stdio.h>
    #include<iostream>
    using namespace std;
    pthread_key_t key;
    pthread_key_t key1;
    pthread_key_t key2;
    void func1(){
    	int *tmp = (int*)pthread_getspecific(key);
    }
    
    void *tthread_fun(void* args){
    	pthread_setspecific(key,args);
    	int *tmp = (int*)pthread_getspecific(key);
    	printf("线程%lu的私有地址为:%p\n",pthread_self(),tmp);
    	*tmp+=1;
    	func1();
    	return (void*)0;		
    }
    
    int main(){
    	pthread_t pa, pb;
    	pthread_key_create(&key,NULL);
    	pthread_key_create(&key1,NULL);
    	pthread_key_create(&key2,NULL);
    	cout<<key<<" "<<key1<<" "<<key2<<endl;
    	pthread_t pid[3];
    	int a[3]={100,200,300};
    	cout<<"the address of array is: "<<&a<<endl;
    	int i=0;
    	for(i=0;i<3;i++){
    		pthread_create(&pid[i],NULL,tthread_fun,&a[i]);
    		cout<<"pthread id is: "<<pid[i]<<endl;
    
    	}
    	for(i=0;i<3;i++){
    		pthread_join(pid[i],NULL);
    
    	}
    	cout<<a[0]<<" "<<a[1]<<" "<<a[2]<<endl;
    	return 0;
    }
    输出结果:

    从测试结果我们可以看出

    (1):key的值是从0(key)开始分配的,然后是1(key1),再然后是2(key2);

    (2):在进程里我们一共创建了3个进程,这三个进程共同使用一个键key(它额值为0),那么对应于每一个线程中的pkey[0]不同的线程的指向不同,就上面的程序而言,pid[0](可以看成线程A)的pkey[0]里存放的是变量a[0]地址,pid[1](可以看成线程B)的pkey[0]里存放的是变量a[1]地址,pid[2](可以看成线程C)的pkey[0]里存放的是变量a[2]地址,这三个变量分别作为这三个线程的私有数据;函数fun1的关联结构为:


    (3):在不同的线程中:

    int *tmp = (int*)pthread_getspecific(key);
    虽然同样是key,但是我们得到的tem的地址对于每个线程来说不同,这些地址也就是图3中pkey[0]所指的地址;


    另外还做了另一个实验:

    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <sys/types.h>
    #include <pthread.h>
    #define THREAD_NUM 3
    
    void * thread_handler(void *arg){
            printf("process id: %d\tthread id: %lu\n", getpid(),pthread_self());
    }
    int main(){
            int i;
            pthread_t tid[THREAD_NUM];
    	printf("process id: %d\tthread id: %lu\n", getpid(),pthread_self());
            for(i = 0; i < THREAD_NUM; i++){
                    pthread_create(&tid[i], NULL, thread_handler, NULL);
            }
            for(i = 0; i < THREAD_NUM; i++){
                    pthread_join(tid[i],NULL);
            }
    	return 0;
    }
    
    输出结果:


    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <sys/types.h>
    #include <pthread.h>
    #define THREAD_NUM 3
    int main(){
            int i;
    	printf("process id: %d\tthread id: %lu\n", getpid(),pthread_self());
    	return 0;
    }

    输出结果:

    从上面两个例子可以看出,进程可以看成是主线程,占用一个线程号!!!!!

    相关文章:

    http://www.cnblogs.com/snake-hand/p/3148191.html
    http://blog.csdn.net/caigen1988/article/details/7901248
    http://www.2cto.com/kf/201312/261554.html
    http://blog.csdn.net/cywosp/article/details/26469435

    展开全文
  • 线程私有数据(Thread-Specific Data)

    千次阅读 2011-05-07 18:54:00
    线程私有数据存在的原因在于有时需要维护基于每个线程的数据,通俗来说就是有些数据在每个线程中都存在,各个线程都应该拥有自己的私有版本,改动自己的数据不应弄乱别人的,假若这些数据是全局的,也就是说不能分配在...

     

    线程私有数据存在的原因在于有时需要维护基于每个线程的数据,通俗来说就是有些数据

    在每个线程中都存在,各个线程都应该拥有自己的私有版本,改动自己的数据不应弄乱别人

    的,假若这些数据是全局的,也就是说不能分配在线程栈中,那怎么办?数据的名称可是一样

    的哦.如果简单地声明一个全局变量,则这个全局变量会被其他线程所共享.

    从数据结构的观点看,这里的要求是每个线程都从同一个名称出发,但能访问到不同的数据

    ,这种类型的数据,很遗憾,不存在.只有通过操作,也就是函数去实现了.

    想想我们能提供什么去获取这个数据吧:线程ID, 数据名称.我首先想到的是使用hash函数

    ,但处理冲突好像很麻烦,这大概就是pthread实现采用键并限制线程私有数据数量的原因

    吧,细节就不管了.

     

    具体操作线程私有数据的函数有:

    int pthread_key_create(pthread_key_t *keyp,

                 void (* destructor )(void *));

    每份私有数据对应着一个keyp,destructor用于线程退出时清理私有数据(明显,私有数据

    不是分配在线程栈上,而是进程堆中).

     

    int pthread_key_delete(pthread_key_t *key);

    用于删除key,但好像没什么用.注意它不会调用destructor,所以要主动清理.

     

    明显,每个线程对每一份私有数据拥有的key应该是一样的,所以不能让多个线程对同一个

    key调用pthread_key_create().解决方法是使用pthread_once():

    int pthread_once(pthread_once_t *initflag, void

         (*initfn)(void));

    initflag要求是非本地变量(例如全局,静态变量),并被初始化为PTHREAD_ONCE_INIT.

    如果每个线程都调用pthread_once()以产生key,系统保证只在第一次调用pthread_once()

    时调用initfn.

    APUE建议使用下面的序列:

    void destructor(void *);

    pthread_key_t key;

    pthread_once_t init_done = PTHREAD_ONCE_INIT;

    void

    thread_init(void)

    {

       err = pthread_key_create(&key, destructor);

    }

    int

    threadfunc(void *arg)

    {

       pthread_once(&init_done, thread_init);

       ...

    }

    那为什么不直接在线程产生之前在主线程调用pthread_create_key()呢?原因是这会暴露

    太多细节,试想私有数据是某个库函数的,主线程又如何得知它使用的key是什么呢?而如果

    库函数要求主线程在生成其它线程之前就调用某个初始化函数,是不是太什么了一点?如果

    说一个库函数调用还可以接受的话,那么大量的库函数调用呢?

     

    当一个key产生之后,我们可以调用pthread_setspecific为这个key关线程私有数据,调用

    pthread_getspecific去获取:

    int pthread_setspecific(pthread_key_t key, const void *value);

    void *pthread_getspecific(pthread_key_t key);

     

     

    以下是APUE利用线程私有数据实现的线程安全getenv:

     

     

    注意ARG_MAX不知道是在哪里定义的,自己定义一个就好,但一定要注意足够大,否则线程结束时free会出错.

    以下是调用该函数的主函数,其中error.h在apue里提供的源码里可能也有吧,我是从unix网络编程(同一个作者)里拿来的:

     

     

     

     

    展开全文
  • 线程私有数据

    2019-10-16 20:38:14
    但有时应用程序设计中必要提供线程私有的全局变量,这个变量仅在线程中有效,但却可以跨过多个函数访问。比如在程序里可能需要每个线程维护一个链表,而会使用相同的函数来操作这个链表,最简单的方法就是使用同名而...

    在多线程程序中,经常要用全局变量来实现多个函数间的数据共享。由于数据空间是共享的,因此全局变量也为所有线程共有。但有时应用程序设计中必要提供线程私有的全局变量,这个变量仅在线程中有效,但却可以跨过多个函数访问。比如在程序里可能需要每个线程维护一个链表,而会使用相同的函数来操作这个链表,最简单的方法就是使用同名而不同变量地址的线程相关数据结构。这样的数据结构可以由 Posix 线程库维护,成为线程私有数据 (Thread-specific Data,或称为 TSD)。

    #include <pthread.h>
    /* 创建一个类型为 pthread_key_t 类型的私有数据变量( key )。 */
    int pthread_key_create(pthread_key_t *key, void (*destructor)(void*));
    /* 参数:
        key:在分配( malloc )线程私有数据之前,需要创建和线程私有数据相关联的键( key ),这个键的功能是获得对线程私有数据的访问权。
        destructor:清理函数名字( 如:fun )。当线程退出时,如果线程私有数据地址不是非 NULL,此函数会自动被调用。该函数指针可以设成 NULL ,这样系统将调用默认的清理函数。
            回调清理函数其定义如下:
            void fun(void *arg)
            {
                // arg 为 key 值
            }
    */
    
    /* 返回值:
        成功:0
        失败:非 0
    */
    
    
    #include <pthread.h>
    
    /* 注销线程私有数据。这个函数并不会检查当前是否有线程正使用线程私有数据( key ),也不会调用清理函数 destructor() ,而只是将线程私有数据( key )释放以供下一次调用 pthread_key_create() 使用。 */
    int pthread_key_delete(pthread_key_t key);
    
    /* 参数:
        key:待注销的私有数据。
    */
    
    /* 返回值:
        成功:0
        失败:非 0
    */
    #include <pthread.h>
    
    /* 设置线程私有数据( key ) 和 value 关联,注意,是 value 的值(不是所指的内容)和 key 相关联。 */
    int pthread_setspecific(pthread_key_t key, const void *value);
    
    /* 参数:
        key:线程私有数据。
        value:和 key 相关联的指针。
    */
    
    /* 返回值:
        成功:0
        失败:非 0
    */
    #include <pthread.h>
    
    /* 读取线程私有数据( key )所关联的值。 */
    void *pthread_getspecific(pthread_key_t key);
    
    /* 参数:
        key:线程私有数据。
    */
    
    /* 返回值:
        成功:线程私有数据( key )所关联的值。
        失败:NULL
    */

    代码

    #include<pthread.h>
    #include<stdio.h>
    #include<unistd.h>
    
    pthread_key_t key;
    
    /* 公用函数 */
    void print(pthread_t pthrd)
    {
        /* 不同的线程可以通过同一个 key 值访问各自的私有数据 */
        printf("I am %lu, value=%d\n",pthrd,*((int*)pthread_getspecific(key)));
        int value = *((int*)pthread_getspecific(key));
    }
    
    /* 创建的第一个线程的回调函数 */
    static void* start_pthread1(void* arg)
    {
        pthread_t pthrd = pthread_self();
        int value = 0;
        /* 将 value 关联 key 值 */
        pthread_setspecific(key,(const void*)&value);
        for (int i = 0; i < 5; i++)
        {
            print(pthrd);
            sleep(1);
        }    
        return NULL;
    }
    
    /* 创建的第二个线程的回调函数 */
    static void* start_pthread2(void* arg)
    {
        pthread_t pthrd = pthread_self();
        int value = 5;
        /* 将 value 关联 key 值 */
        pthread_setspecific(key,(const void*)&value);
        for (int i = 0; i < 5; i++)
        {
            print(pthrd);
            sleep(1);
        }    
        return NULL;
    }
    
    int main()
    {
        pthread_t thread1;
        pthread_t thread2;
        
        /* 创建私有数据 */
        pthread_key_create(&key,NULL);
    
        /* 创建线程 */
        pthread_create(&thread1,NULL,start_pthread1,(void*)("number one"));
        pthread_create(&thread2,NULL,start_pthread2,(void*)("number two"));
    
        /* 等待线程结束,回收资源 */
        pthread_join(thread1,NULL);
        pthread_join(thread2,NULL);
    
        /* 删除私有数据 */
        pthread_key_delete(key);
    
        return 0;
    }

    执行可见,在不同线程里,key 关联这不同的数据,此时这些数据就是线程私有的。

     lingyun@manjaro  ~/Document/CppCode/study  gcc study.cpp -o study -lpthread -g
     lingyun@manjaro  ~/Document/CppCode/study  ./study                            
    I am 140440438978304, value=0
    I am 140440430585600, value=5
    I am 140440430585600, value=5
    I am 140440438978304, value=0
    I am 140440430585600, value=5
    I am 140440438978304, value=0
    I am 140440438978304, value=0
    I am 140440430585600, value=5
    I am 140440438978304, value=0
    I am 140440430585600, value=5
     lingyun@manjaro  ~/Document/CppCode/study  

     

    展开全文
  • 【Linux】Linux线程私有数据

    千次阅读 2019-02-05 15:44:53
    线程私有数据 在单线程程序中,函数经常使用全局变量或静态变量,这是不会影响程序的正确性的,但如果线程调用的函数使用全局变量或静态变量,则很可能引起错误。因为这些函数使用的全局变量和静态变量无法为不同的...

    线程私有数据

    在单线程程序中,函数经常使用全局变量或静态变量,这是不会影响程序的正确性的,但如果线程调用的函数使用全局变量或静态变量,则很可能引起错误。因为这些函数使用的全局变量和静态变量无法为不同的线程保存各自的值,而当同一进程内的不同线程几乎同时调用这样的函数时就可能会有问题发生。

    而解决这一问题的一种方式就是使用线程私有数据。线程私有数据采用了一种被称为一键多值的技术,即一个键对应多个数值。访问数据时都是通过键值来访问,好像是对一个变量进行访问,其实是在访问不同的数据。使用线程私有数据时,首先要为每个线程数据创建一个相关联的键。在各个线程内部,都使用这个公用的键来指代线程数据,但是在不同的线程中,这个键代表的数据是不同的。

    这和JAVA中的ThreadLocal变量的思想有点像:尽管是一个变量,但是在不同的线程中调用就是取出的不同的值。

    设计线程私有数据的原因:

    • 在维护每个线程的私有数据的时候,我们可能会想到分配一个保存线程数据的数组,用线程的ID作为数组的索引来实现访问,但是有一个问题是:系统生成的线程ID不能保证是一个小而连续的整数, 并且用数组实现的时候由于其他线程也可以访问其数组中的数据,这样会引起数据的不安全;
    • 线程私有数据提供了让基于进程的接口适应多线程环境的机制。

    一个很明显的实例就是errno,以前的接口(线程出现以前)把errno定义为进程上下文中全局可访问的整数。系统调用和库例程在调用或执行失败时设置 errno,把它作为操作失败的附属结果。为了让线程也能够使用那些原本基于进程的系统调用和库例程,errno 被重定义为线程私有数据。这样,一个线程做了重置errno的操作也不会影响进程中其他线程的errno值。

     

    线程私有变量函数

    线程私有变量的相关函数为:

    线程私有变量的初始化

    int pthread_key_create (pthread_key_t *key, void (*destructor)(void *));

    函数说明:key参数为指向一个键值的指针,第二个参数指明了一个destructor函数,如果这个参数不为空,那么当每个线程结束时,系统将调用这个函数来释放绑定在这个键上的内存块。

    销毁线程私有变量

    int pthread_key_delete (pthread_key_t key);

    函数说明:key参数为一个键值。

    向线程私有变量赋值

    int pthread_setspecific (pthread_key_t key, const void *value);

    函数说明:value参数是不同的线程中,key值所关联的私有数据地址,这些地址可以用malloc来分配。

    获取线程私有变量

    void *pthread_getspecific (pthread_key_t key);

    函数说明:key参数为一个键值,返回值是线程私有变量的数据地址。

    指定函数只执行一次

    int phread_once(pthread_once_t *onceptr, void(*init)(void));

    函数说明:本函数使用初值为PTHREAD_ONCE_INIT的once_control变量保证init_routine()函数在本进程执行序列中仅执行一次。注意的是,onceptr必须是一个非本地变量(即全局变量或者静态变量),而且必须初始化为PTHREAD_ONCE_INIT。

    一般使用环境:在多线程环境中,有些事仅需要执行一次。通常当初始化应用程序时,可以比较容易地将其放在main函数中。但当你写一个库时,就不能在main里面初始化了,你可以用静态初始化,但使用一次初始化(pthread_once)会比较容易些。

    例子:

    pthread_key_t key;
    pthread_once_t r1_once = PTHREAD_ONCE_INIT;
    
    void destructor(void *ptr){
             free(ptr);
    }
    
    void excute_once(void)  {
            pthread_key_create(&key, destructor);
    }
    
    int main(){
           pthread_once(&r1_once, excute_once);
    }

     

    TSD池

    作为TSD池,就是线程私有数据(Thread-specific Data)池。

    当我们调用pthread_key_create()时,内核从Linux的TSD池中分配一项,将其值赋给key供以后访问使用,它的第一个参数key为指向键值的指针,第二个参数为一个函数指针,如果指针不为空,则在线程退出时将以key所关联的数据为参数调用destr_function(),释放分配的缓冲区。 key一旦被创建,所有线程都可以访问它,但各线程可以根据自己的需要往key中填入不同的值,这就相当于提供了一个同名而不同值的全局变量,一键多值。其中TSD池的结构如下:

    内核支持的pthread_keys是有限的(一般是128),除了进程范围内的keys结构数组之外,系统还在进程内维护了关于多个线程的多条信息。这些特定于线程的信息我们称之为Pthread结构。其中部分内容是我们称之为pkey数组的一个128个元素的指针数组。系统维护的关于每个线程的信息结构图如下:

    一旦我们在某个线程里面调用pthread_setspecific()将key与某个空间(这个空间可以是malloc申请的)相关连的时候,上面的结构就变成:

     

    实际例子

    #include<stdio.h>
    #include<unistd.h>
    #include<pthread.h>
     
    pthread_key_t key;
     
    void echomsg( void* param )
    {
            printf( "destructor excuted in thread %lu, param = %lu\n", pthread_self(), *((unsigned long int*)param) );
    }
     
    void* child1( void* param )
    {
            unsigned long int  tid = pthread_self();
            printf( "thread %lu enter\n", tid );
            pthread_setspecific( key, ( void* )tid );
     
            sleep( 2 );
            unsigned long int  val = *((unsigned long int *)pthread_getspecific( key ));
            printf( "thread %lu returns %lu\n", tid, val );
            sleep( 5 );
     
            return ( void* )0;
    }
     
     
    void* child2( void* param )
    {
            unsigned long int tid = pthread_self();
            printf( "thread %lu enter\n", tid );
            pthread_setspecific( key, ( void* )tid );
     
            sleep( 1 );
            unsigned long int  val = *( (unsigned long int*)pthread_getspecific( key ) );
            printf( "thread %lu returns %lu\n", tid, val );
            sleep( 5 );
     
            return ( void* )0;
    }
     
    int main()
    {
            pthread_t tid1, tid2;
            printf( "main thread enter\n" );
     
            pthread_key_create( &key, echomsg );
            pthread_create( &tid1, NULL, child1, NULL );
            pthread_create( &tid2, NULL, child2, NULL );
     
            sleep( 10 );
            pthread_key_delete( key );
            printf( "main thread exit\n" );
     
            return 0;
    }
    

    通过g++编译命令:

    g++ -lpthread -o TSD.out TSD.cpp

    最终的运行结果为:

    kennie@cbib:~/pthreadDIR$ ./TSD.out
    main thread enter
    thread 3075607408 enter
    thread 3067214704 enter
    thread 3067214704 returns 3067214704
    thread 3075607408 returns 3075607408
    destructor excuted in thread 3067214704, param = 3067214704
    destructor excuted in thread 3075607408, param = 3075607408
    main thread exit

     

    参考文章:线程特定数据TSD及其实现原理linux线程私有数据详解线程私有数据

     

    展开全文
  • 复习以前做过的爬虫系统,在做防止死链时用到了线程私有数据,那时候仅仅是会用,至于底层是怎么实现的以及为什么一个键可以对应不同线程的指还一知半解,今天又详细的看了下相关的资料,以做总结。  在维护每个...
  • 一、线程概述   在许多经典的操作系统教科书中,总是把进程定义为程序的执行实例,它并不执行什么, 只是维护应用程序所需的各种资源,而线程则是真正的执行实体。在一个进程中的多个执行路线叫做线程。为了让进程...
  • 线程私有数据实现的原理

    千次阅读 2015-08-10 17:23:53
    在维护每个线程的私有数据的时候,我们可能会想到分配一个保存线程数据的数组,用线程的ID作为数组的索引来实现访问,但是有一个... 线程私有数据实现的主要思想是:在分配线程私有数据之前,创建与该数据相关联的健,
  • 多线程编程之线程私有数据  Pthread是 POSIX threads 的简称,是POSIX的线程标准。  线程同步从互斥量【C/C++多线程编程之六】pthread互斥量,信号量【C/C++多线程编程之七】pthread信号量,条件变量【C...
  • Linux系统编程——线程私有数据

    万次阅读 2016-12-23 11:55:58
    在多线程程序中,经常要用全局变量来实现多个函数间的数据共享。由于数据空间是共享的,因此全局变量也为所有线程...这样的数据结构可以由 Posix 线程库维护,成为线程私有数据 (Thread-specific Data,或称为 TSD)。
  • Java虚拟机运行时数据区域

    万次阅读 2017-11-30 14:02:00
    由此图可以看出 线程共享的数据区有 方法区和堆 线程隔离的数据区有 虚拟机栈 本地方法栈和程序计数器 按照我自己的理解概括一下这几个区...因为是线程私有的,所以每个线程都是有这样一个指示器的,字节码解释器就是按照
  • 但同时线程需要保留一些自己私有数据 unix中的thread独自持有的资源: Stack pointerRegistersscheduling properties(policy and priority)set of pending and blocked signalsThread specific data 线程操作的...
  • UNIX环境高级编程——线程私有数据

    千次阅读 2013-07-18 15:00:29
    下面说一下线程中特有的线程存储,Thread Specific Data 。线程存储有什么用了?他是什么意思了?大家都知道,在多线程程序中,所有线程共享程序中的变量。现在有一全局变量,所有线程都可以使用它,改变它的值。而...
  • 线程共享指的就是可以允许被所有线程共享访问的一块内存,包括堆区,方法区和运行时常量池。  1. java堆区  java堆区在虚拟机启动时被创建,并且他在实际内存中是可以不连续的。java堆区是用于存储对象实例的一...
  • 基础面试题:java内存区域

    万次阅读 2020-04-11 21:41:10
    线程私有数据区域生命周期与线程相同, 依赖用户线程的启动/结束 而 创建/销毁(在 Hotspot VM 内, 每个线程都与操作系统的本地线程直接映射, 因此这部分内存区域的存/否跟随本地线程的生/死对应)。13/04/2018 Page 22...
  • JVM-内存模型

    万次阅读 2019-02-16 10:42:48
    程序计数器:线程私有;记录指令执行的位置;这里不会出现OutOfMemoryError 虚拟机栈:线程私有;生命周期和线程一致;存储局部变量表、操作数栈、动态链接、方法出口等信息。(局部变量表:存放了编译期可知的各种...
  • 线程私有数据

    千次阅读 2012-07-24 11:32:17
    1.为什么需要线程私有数据: 原因一:有时候需要维护基于每个线程的数据,用线程ID作为索引。因为线程ID不能保证是小而连续的整数,所以不能简单的分配一个线程数据数组,用线程ID作为数组的索引。即使线程ID确实是...
  • 进程是具有一定独立功能的程序关于某个数据集合上的一次运行活动,进程是系统进行资源分配和调度的一个独立单位。 线程是进程的一个实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位。线程...
  • 线程私有与共享

    千次阅读 2018-05-22 21:09:53
    线程私有:栈(局部变量,函数的参数)线程局部存储(Thread Local Storage,TLS)。有限的容量寄存器 (执行流的基本数据)TLS的用法很简单,如果要定义一个全局变量为TLS类型,只需在她定义前加上相应的关键字即可...
  •  一、引言 在并行区域中,若多个线程共同访问同一存储单元,并且至少会有一个线程更新数据单元中的内容时,会发送数据今生。本节的数据共享与私有化对数据竞争做一个初步的探讨,后续会在同步、互斥相关...
  • 在APUE(第二版)这本书中看到了第12章,12.6中讲线程私有数据。为使每个线程可以独立地访问数据副本,在线程的执行函数中调用pthread_key_create()来为该线程创建一个键,通过这个键再用pthread_getspecific()和...
1 2 3 4 5 ... 20
收藏数 148,791
精华内容 59,516
热门标签
关键字:

线程私有数据