Linux multithreaded Practice (4)-Thread-specific data

Source: Internet
Author: User

thread-specific data
int Pthread_key_create (pthread_key_t *key, Void (*destr_function) (void *)); int pthread_key_delete (pthread_key_t key); int pthread_setspecific (pthread_key_t key, const void *pointer), void * pthread_getspecific (pthread_key_t key);p Thread_ once_t Once_control = Pthread_once_init;int pthread_once (pthread_once_t *once_control, Void (*init_routine) (void));

In a single-threaded program, we often use "global variables" to implement shared data between multiple functions, but in a multithreaded environment, because the data space is shared, global variables are common to all threads. But sometimes it is necessary in application design to provide a thread-private global variable that is valid only in one thread, but can be accessed across multiple functions . The POSIX line libraries solves this problem by maintaining a certain data structure, which is called (Thread-specific-data or TSD), and the thread-specific data is as shown:

It is known that when Pthread_key_create is called, it produces a key value for thread-specific data (TSD) that is visible to all threads (such as all threads in a pkey[1] value), but the actual data that this key points to is different. Although they are all pkey[1], they do not point to the same piece of memory, but instead point to their own actual data, so if thread 0 changes the data pointed to by pkey[1], it is not able to image to thread n;

    After a thread calls Pthread_setspecific, the specific data for each of the threads is bound to thread_key_t, although there is only one pthread_key_t, but the specific data for each thread is a separate memory space. The destructor  function is executed when the thread exits.

/** Example 1: set/Get thread-specific data set/get thread-specific data in two threads, see if data in two threads is the same (definitely not the same O (∩_∩) o~) **/pthread_key_t key;typedef struct tsd{    pthread_t Tid; char *str;}    tsd_t;//is used to destroy the actual data that each thread points to, void destructor_function (void *value) {free (value); cout << "destructor ..." << Endl;}    void *thread_routine (void *args) {//Set thread-specific data tsd_t *value = (tsd_t *) malloc (sizeof (tsd_t));    Value->tid = Pthread_self ();    VALUE-&GT;STR = (char *) args;    Pthread_setspecific (key, value);    printf ("%s setspecific, Address:%p\n", (char *) args, value);    Get thread-specific data value = (tsd_t *) pthread_getspecific (key);    printf ("tid:0x%x, str =%s\n", (unsigned int) value->tid, value->str);    Sleep (2);    Get thread-specific data again value = (tsd_t *) pthread_getspecific (key);    printf ("tid:0x%x, str =%s\n", (unsigned int) value->tid, value->str); Pthread_exit (NULL);}     int main () {//So each thread will have a key available,//But each key is bound to the actual area required by each thread to specify Pthread_key_create (&key, destructor_function); pthread_t Tid1, Tid2;    Pthread_create (&tid1, NULL, Thread_routine, (void *) "thread1");    Pthread_create (&tid2, NULL, Thread_routine, (void *) "thread2");    Pthread_join (TID1, NULL);    Pthread_join (Tid2, NULL);    Pthread_key_delete (key); return 0;}
/** Example 2: Use Pthread_once to initialize key only once note: The initialization of key is put into init_routine **/pthread_key_t key;pthread_once_t Once_control =    pthread_once_init;typedef struct tsd{pthread_t tid; char *str;}    tsd_t;//thread-specific data destruction functions,//used to destroy the actual data pointed to by each thread void destructor_function (void *value) {free (value); cout << "destructor ..." << Endl;} Initialize the function, put the initialization of the key into the function,//can guarantee that the Inti_routine function only runs once void Init_routine () {pthread_key_create (&key, Destructor_    function); cout << "init ..." << Endl;}    void *thread_routine (void *args) {pthread_once (&once_control, init_routine);    Set thread-specific data tsd_t *value = (tsd_t *) malloc (sizeof (tsd_t));    Value->tid = Pthread_self ();    VALUE-&GT;STR = (char *) args;    Pthread_setspecific (key, value);    printf ("%s setspecific, Address:%p\n", (char *) args, value);    Get thread-specific data value = (tsd_t *) pthread_getspecific (key);    printf ("tid:0x%x, str =%s\n", (unsigned int) value->tid, value->str);    Sleep (2); Get thread-specific data again value = (tsd_t *) pThread_getspecific (key);    printf ("tid:0x%x, str =%s\n", (unsigned int) value->tid, value->str); Pthread_exit (NULL);}    int main () {pthread_t tid1, Tid2;    Pthread_create (&tid1, NULL, Thread_routine, (void *) "thread1");    Pthread_create (&tid2, NULL, Thread_routine, (void *) "thread2");    Pthread_join (TID1, NULL);    Pthread_join (Tid2, NULL);    Pthread_key_delete (key); return 0;}


Attached-linux/unix thread Private data realization idea:

Original link:http://blog.csdn.net/caigen1988/article/details/7901248

The main idea of a thread-private data implementation is to create a key associated with the data before it is allocated, which can be used by all threads in the process, but each thread associates the key with a different thread private data address . It is necessary to note that each system supports a limited number of thread-specific data elements (for example, 128 limit). So what is the key implementation principle?

   in fact, each process is maintained by a system calledKeyStructure an array of structures, as shown in:


(Fig. 1)

the "flag" in the key structure indicates whether the data element is in use. At the beginning, all flags are initialized to "not in use." When a thread calls Pthread_key_create to create a new thread-specific data element, the system searches for an array of key structures to find the first "not used" element. The index of the element (0~127, called the "key") is returned to the calling thread.

In addition to the process-wide array of key structures, the system maintains multiple threads of information within a process. These thread-specific information we call the pthread structure. Part of this is an array of pointers to the 128 elements we call the Pkey array. The information structure for each thread maintained by the system is as follows:

(Fig. 2)

in, all elements of the Pkey array are initialized to null pointers. These 128 pointers are the values that are associated with each of the 128 possible keys in the process.

So what does the system do for us when we call the Pthread_key_create function?

The system first returns to us the first "unused" key (that is, the index value) in an array of key structures, where each thread can then find the corresponding position and store a value (pointer) for that location. Generally, this pointer is usually obtained by calling malloc for each thread.

Knowing the approximate principle of private data implementation, how do you use thread-specific data in programming?

Suppose a process is started and multiple threads are created. One of the threads calls Pthread_key_create. The system finds a 1th unused element in the key structure array (Figure 1). and returns its index (0~127) to the caller. We assume that the index found is 1.

After the thread calls Pthread_getspecific to get the value of the pkey[1] of this thread (a pointer to the value of key 1 in Figure (2)), the return value is a null value, and the thread then calls malloc to allocate the memory area and initialize the memory area. The thread then calls Pthread_setspecific to set the thread-specific data pointer (Pkey[1]) of the corresponding created key to point to the memory area it just allocated. Points out the situation at this time.

(Fig. 3)

Knowing how to get the specific data value of a thread, what does the system do if the thread terminates?

We know that when a thread calls Pthread_key_create to create a particular data element, one of the parameters specified is a pointer to a destructor. When a thread terminates, the system scans the thread's Pkey array and invokes the corresponding destructor for each non-empty pkey pointer. The corresponding destructor is a function pointer stored in the key array in Figure 1. This is a means of releasing thread-specific data when a thread terminates.

Linux multithreaded Practice (4)-Thread-specific data

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.