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 . POSIX line libraries solves this problem by maintaining a certain data structure, which is called (Thread-specific-data or TSD).
The relevant functions are as follows:
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); pthread_once_t Once_control = pthread_once_init; int pthread_once (pthread_once_t *once_control, Void (*init_routine) (void));
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 all pkey[1], But instead of pointing to the same piece of memory, they point to the actual data that belongs to them, so if thread 0 changes the data pointed to by pkey[1], it is not able to image to thread n;
< Span style= "font-family: ' Courier New '" > thread call Pthread_ Setspecific binds specific data for each thread to thread_key_t, although there is only one pthread_key_t, but the specific data for each thread is a separate memory space, and the destructor function executes when the thread exits.
/** Example 1: Using Pthread_once, let key only initialize 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; The thread-specific data destruction function//is used to destroy the actual data pointed to by each thread void destructor_function (void *value) {free (value); cout << "destructor ..." << Endl; }//initialization function, put the initialization of key into the function,//can guarantee that the Inti_routine function only runs once void Init_routine () {pthread_key_create (&key, Destru Ctor_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->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; }
The results of the operation are as follows:
Init....
Thread1 setspecific, address:0x7fe7a00008c0
tid:0xa8192700, str = thread1
Thread2 setspecific, address:0x7fe7980008c0
tid:0xa7991700, str = thread2
tid:0xa8192700, str = thread1
tid:0xa7001700, str = thread2
destructor ...
destructor ...
The main thread creates two threads and then joins waits for them to exit; the execution function for each thread is called pthread_once in Thread_routine,thread_routine, which means that it executes if the first thread calls it Once_ Routine, and then returns from Once_routine, which is pthread_once, and the next thread calls it no longer executes once_routine, in order to call pthread_key_create only once, A pthread_key_t value is generated.
In the Thread_routine function, you customize the type of thread-specific data, for different threads say the content of TSD is different, assuming that thread 1 in the first print to sleep, thread 2 also began to execute and call pthread_setspecific bound thread 2 of the TSD and key_t, when thread 1 calls pthread_getspecific returns the key_t bound TSD pointer, it is still the TSD pointer of thread 1, that is, although there is only one key_t, each thread has its own TSD.
specific data; with the key-value Implementation, a thread creates a key, another thread creates it, But not pointing to the same fast memory, they point to their own data,
This is thread-specific data.
In the code above, even Sleeep (2), thread 1 's data is not affected by thread 2 's data, because it is thread-private.
When the thread exits, it is destroyed 2 times because two threads were created.
where Tid is the thread's id,str is passed to the Thread_routine parameter, you can see that there are two different ptr, and the destroy is called two times.
In addition, the idea of Linux/unix thread private data implementation :
Please refer to http://blog.csdn.net/caigen1988/article/details/7901248, write very well.
Linux Multithreading Practice (iv) specific data for threads