pthread_key_t和pthread_key_create()詳解
下面說一下線程中特有的線程存儲, Thread Specific Data 。線程存儲有什么用了?他是什么意思了?大家都知道,在多線程程序中,所有線程共享程序中的變量。現在有一全局變量,所有線程都可以使用它,改變它的值。而如果每個線程希望能單獨擁有它,那么就需要使用線程存儲了。表面上看起來這是一個全局變量,所有線程都可以使用它,而它的值在每一個線程中又是單獨存儲的。這就是線程存儲的意義。
下面說一下線程存儲的具體用法。
1. 創建一個類型為 pthread_key_t 類型的變量。
2. 調用 pthread_key_create() 來創建該變量。該函數有兩個參數,第一個參數就是上面聲明的 pthread_key_t 變量,第二個參數是一個清理函數,用來在線程釋放該線程存儲的時候被調用。該函數指針可以設成 NULL ,這樣系統將調用默認的清理函數。
3. 當線程中需要存儲特殊值的時候,可以調用 pthread_setspcific() 。該函數有兩個參數,第一個為前面聲明的 pthread_key_t 變量,第二個為 void* 變量,這樣你可以存儲任何類型的值。
4. 如果需要取出所存儲的值,調用 pthread_getspecific() 。該函數的參數為前面提到的 pthread_key_t 變量,該函數返回 void * 類型的值。
下面是前面提到的函數的原型:
int pthread_setspecific(pthread_key_t key, const void *value);
void *pthread_getspecific(pthread_key_t key);
int pthread_key_create(pthread_key_t *key, void (*destructor)(void*));
下面是一個如何使用線程存儲的例子:

Code#include <malloc.h>
#include <pthread.h>
#include <stdio.h>
/* The key used to associate a log file pointer with each thread. */
static pthread_key_t thread_log_key;
/* Write MESSAGE to the log file for the current thread. */
void write_to_thread_log (const char* message)
{
FILE* thread_log = (FILE*) pthread_getspecific (thread_log_key);
fprintf (thread_log, “%s\n”, message);
}
/* Close the log file pointer THREAD_LOG. */
void close_thread_log (void* thread_log)
{
fclose ((FILE*) thread_log);
}
void* thread_function (void* args)
{
char thread_log_filename[20];
FILE* thread_log;
/* Generate the filename for this thread’s log file. */
sprintf (thread_log_filename, “thread%d.log”, (int) pthread_self ());
/* Open the log file. */
thread_log = fopen (thread_log_filename, “w”);
/* Store the file pointer in thread-specific data under thread_log_key. */
pthread_setspecific (thread_log_key, thread_log);
write_to_thread_log (“Thread starting.”);
/* Do work here... */
return NULL;
}
int main ()
{
int i;
pthread_t threads[5];
/* Create a key to associate thread log file pointers in thread-specific data. Use close_thread_log to clean up the file pointers. */
pthread_key_create (&thread_log_key, close_thread_log);
/* Create threads to do the work. */
for (i = 0; i < 5; ++i)
pthread_create (&(threads[i]), NULL, thread_function, NULL);
/* Wait for all threads to finish. */
for (i = 0; i < 5; ++i)
pthread_join (threads[i], NULL);
return 0;
}
最后說一下線程的本質。
其實在Linux 中,新建的線程並不是在原先的進程中,而是系統通過一個系統調用clone() 。該系統copy 了一個和原先進程完全一樣的進程,並在這個進程中執行線程函數。不過這個copy 過程和fork 不一樣。copy 后的進程和原先的進程共享了所有的變量,運行環境(clone的實現是可以指定新進程與老進程之間的共享關系,100%共享就表示創建了一個線程)。這樣,原先進程中的變量變動在copy 后的進程中便能體現出來。
參考鏈接:http://blog.csdn.net/lwfcgz/article/details/37570667
http://blog.csdn.net/lmh12506/article/details/8452700