Thread-specific Data TSD summary

Source: Internet
Author: User

    • The essence of a thread
    • Introduction of second-tier model
    • Three-thread-specific data
    • Four key function descriptions
    • What's the principle of five-inquiring
    • Six Private data usage examples
    • Seven reference documents

First, the nature of the thread

Linux threads, also known as lightweight processes (LWP), say that the thread nature is implemented by sharing user space simulations between processes.

Second, threading model introduction

Threading model is introduced for data sharing, why introduce thread-private data? Sometimes you want to adapt the process-based interface to the multithreaded environment, it is necessary to maintain a private data for each thread, the most typical is errno.

While maintaining the private data for each thread, we might think of allocating an array of stored thread data, using the thread's ID as an index to the array for access.
1. The system-generated thread ID is not guaranteed to be a small, sequential integer
2. When the array is implemented, it is prone to cross-read and write.
Given these two issues, we can use the thread's private data (TSD) to solve this problem.

Third, thread-specific data

Threading Private data (thread specific) is a mechanism for storing and querying data related to a thread. This data is referred to as thread-private data or thread-specific data because you want each thread to have independent access to the copy of the data, eliminating the need to consider multithreading synchronization issues.

Tip: All threads in the process can access the entire address space of the process. In addition to using registers (the only private storage a thread really owns is the processor's register), threads have no way to prevent other threads from accessing its data, and thread-private data is no exception. While the underlying implementation section does not prevent this access, functions that manage thread-private data can improve data independence between threads.

Iv. Description of key functions
  • int Pthread_key_create (pthread_key_t *keyp,void (*destructor) (void *));
    Return value: Returns 0 if successful, otherwise returns the error number
    function: The created key is stored in the memory unit that the KEYP points to, and this key can be used by all threads in the process, but each thread associates the key with a different thread private data address.
    Description:

      1. Creates a thread-private data key that must be guaranteed to be called only once for each pthread_key_t variable, because if a key is created two times, it is actually creating two different keys. The second key overrides the first key, the first key, and the thread private data value that any thread might associate with will be lost. The solution to this competition is to use pthread_once .

        pthread_once_t initflag = Pthread_once_init ;
        int pthread_once (pthread_once_t *initflag, Void (*INITFN) (void));
        Return value: Returns 0 if successful, otherwise returns the error number
        Description: Initflag must be a non-local variable (that is, a global variable or a static variable) and must be initialized to Pthread_once_init.

      2. When a thread calls pthread_exit or a thread executes a return, if the private data is not empty and the destructor is registered, the destructor is called, but if the thread calls the destructor Note 1 is not called when exit , _exit , _exit , abort , or other unhealthy exits occur. The

      3. thread can assign multiple key note 2 to thread-private data, and each key can have a destructor associated with it. The destructors for each key can be different, but they can also use the same destructor. When the
      4. thread exits, the destructor for the thread-private data is called in the order defined in the operating system implementation. A destructor might call another function that might create a new thread-private data and associate that data with the current key. When all destructors have been called, the system checks to see if there are non-null thread private data values associated with the key and, if any, calls the destructor again. This process repeats until the thread all keys are null-valued thread-private data, or the maximum number of attempts has been made to note 3. When
      5. creates a new key, the data address of each thread is set to NULL.
  • int pthread_key_delete(pthread_key_t *keyp);
    Return value: Returns 0 if successful, otherwise returns the error number
    Function: The association between the cancellation key and the thread private data value.
    Description

    1. pthread_deleteThe call does not activate the destructor associated with the key, which can easily cause a memory leak. To free up memory space for any thread-private data value corresponding to the key, additional steps need to be taken in the application. When the thread private Data key is deleted, it does not affect the thread private data value set by any thread on the key, or even the calling thread's current key value. It is recommended that the thread private data key be removed at the end, especially if some threads still hold the value of that key. Using a private data key that has been deleted will result in undefined behavior.
V. What is the principle of inquiring

The main idea of thread private data implementation,

Within the system, two kinds of data, pthread_key_struct struct arrays and structs are maintained for each process pthread :
1. The "flag" of the PTHREAD_KEY_STRUCT structure indicates whether the data element is in use, and of course all the flags are initialized to "not used" at the beginning;
2. Part of the pthread structure is a 128-element array of pointers that we call a pkey array;
3. You need to call pthread_key_create create a health associated with the data before assigning the thread private data. The system searches the pthread_key_struct structure array, finds the first "not in use" element, and the index of the element (0~127) is called the "key", which is the index returned to the calling thread. This key can be used by all threads in the process, and each thread associates the key with a different thread private data address (personal humble opinion: The association here refers to the use of the same index). Although the index values are the same, the result is that each thread gets a different value from the same index (the value is the private data that is stored) because the start address of the Pkey array is different for each thread.

Vi. Examples of private data usage
/* * TSD (Thread specific Data) using step description * Operating environment: Slackwarelinux 64bit */#include <stdio.h>#include <pthread.h>///1, create a variable of type pthread_key_t typepthread_key_t key;voiddestructor (void*arg) {//arg is the stored thread data    printf("destructor executed in thread%lx, param =%lx\n", Pthread_self (), Arg);}void* CHILD1 (void*arg) {pthread_t tid = pthread_self ();printf("Thread1%lx entering\n", Tid);///3, thread data storage.     //param1 is the previously declared pthread_key_t key,    //PARAM2 is the data to be stored, the void* type description can store any type of dataPthread_setspecific (Key, (void*) tid); Sleep2);//Yield CPU    //4, remove the stored thread data.     //param for the previously mentioned pthread_key_t key    //If no thread-private data value is associated with the key, Pthread_getspecific will return a null pointer, which can be used to determine if the call to Pthread_setspecific is required.     printf("Thread1%lx returned%lx\n", Tid, pthread_getspecific (Key));}void*child2 (void*arg) {pthread_t tid = pthread_self ();printf("Thread2%lx entering\n", Tid); Pthread_setspecific (Key, (void*) tid); Sleep1);printf("Thread2%lx returned%lx\n", Tid, pthread_getspecific (Key));}intMainintargcChar*argv[]) {pthread_t tid1, Tid2;printf("Main thread%lx entering\n", Pthread_self ());///2, associate key with different thread private data address    //The first parameter is the address of the key declared in step 1;    The second parameter is a function that cleans up the thread store, and the function pointer that is not a dynamic request can be set to NULL;Pthread_key_create (&key, destructor);    Pthread_create (&AMP;TID1, NULL, child1, NULL);    Pthread_create (&tid2, NULL, child2, NULL);    Pthread_join (TID1, NULL); Pthread_join (Tid2, NULL);///5. Disassociate key from thread private data addressPthread_key_delete (key);printf("Main thread%lx returned\n", Pthread_self ());return 0;}

Run results

[email protected]:/scratchbox/test/lidonghai# ./a.outinin thread b7732b90, param = b7732b90main thread b77336c0 returned
/* * Three threads: main thread, th1,th2 each has its own private data area */#include <stdio.h>#include <string.h>#include <stdlib.h>#include <pthread.h>Staticpthread_key_t Str_key;//Create a variable of type pthread_key_t typeStaticpthread_once_t str_alloc_key_once = Pthread_once_init;//define A static variable that is only being allocated onceStatic voidStr_alloc_key ();Static voidSTR_ALLOC_DESTROY_ACCU (void* ACCU);Char* Str_accumulate (Const Char* s) {Char* ACCU; Pthread_once (&str_alloc_key_once,str_alloc_key);//str_alloc_key () This function is called only onceAccu = (Char*) pthread_getspecific (Str_key);//Get the first address of the private data space associated with the keyword corresponding to the thread    if(Accu==null) {//Each newly created thread this value must be null (no point to any allocated data space)accu=malloc(1024x768);if(!ACCU)returnNULL; accu[0] =0; Pthread_setspecific (Str_key, (void*) ACCU);//Set the private data space associated with the keyword for this thread        printf("Thread%lx:allocating buffer at%p\n", Pthread_self (), ACCU); }strcat(accu,s);returnAccu;}Static voidStr_alloc_key () {pthread_key_create (&AMP;STR_KEY,STR_ALLOC_DESTROY_ACCU);//Creates a keyword and its corresponding memory-deallocation function, which is NULL when the process creates a keyword.     printf("Thread%lx:allocated key%d\n", Pthread_self (), Str_key);}Static voidSTR_ALLOC_DESTROY_ACCU (void* Accu) {printf("Thread%lx:freeing buffer at%p\n", Pthread_self (), ACCU); Free(ACCU);}//Thread entry functionvoid* Process (void*arg) {Char* RES; Res=str_accumulate ("Result of");if(strcmp((Char*) ARG,"First")==0) Sleep (3); Res=str_accumulate ((Char*) arg); Res=str_accumulate ("Thread");printf("Thread%lx: \"%s\ "\ n", Pthread_self (), res);returnNULL;}//main thread functionintMainintargcChar* argv[]) {Char* RES;    pthread_t th1,th2; Res=str_accumulate ("Result of"); Pthread_create (&th1,null,process, (void*)"First"); Pthread_create (&th2,null,process, (void*)"Second"); Res=str_accumulate ("Initial thread");printf("Thread%lx: \"%s\ "\ n", Pthread_self (), res);    Pthread_join (Th1,null);    Pthread_join (Th2,null); Pthread_exit (0);}

Run results

[[email protected]10  h57 c]#./pthread_private_data  Thread b7fdd6c0:allocated key 0  Thread b7fdd6c0:allocating buffer at 0  x911c008thread b7fdd6c0: " Result of initial thread " thread b7fdcb90:allocating buffer at 0  X911c938thread b75dbb90:allocating buffer at 0  x911CD  40Thread b75dbb90:  "Resule of second thread"  thread b75dbb90:freeing buffer at Span class= "Hljs-number" >0 x911CD  40Thread b7fdcb90:  "Resule of First thread"  Thread b7fdcb90:freeing buffer at 0  x911c938thread b7fdd6c0:freeing buffer at 0  x911c008 
Vii. Reference Documents

http://blog.csdn.net/caigen1988/article/details/7901248
Http://blog.chinaunix.net/uid-8917757-id-2450452.html
http://www.3fwork.com/b902/001375MYM016745/

Thread-specific Data TSD summary

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.