线程数据
来实现,通过一个键值pthread_key_t
来实现
键值的创建
函数原型:
/* Create a key value identifying a location in the thread-specific
data area. Each thread maintains a distinct thread-specific data
area. DESTR_FUNCTION, if non-NULL, is called with the value
associated to that key when the key is destroyed.
DESTR_FUNCTION is not called if the value associated is NULL when
the key is destroyed. */
extern int pthread_key_create (pthread_key_t *__key,
void (*__destr_function) (void *))
__THROW __nonnull ((1));
第一个参数:就是一个键值的指针
第二个参数:一个destructor
函数,可以传NULL
,如果不为空,当每个线程结束时,调用这个函数来释放绑定在这个键值上的内存快(这个参数很厉害,Demo中有使用说明)。
注:
值得注意的是,这个函数往往和pthread_once()
函数一起使用,目的是让这个键值只被创建一次
/* Guarantee that the initialization function INIT_ROUTINE will be called
only once, even if pthread_once is executed several times with the
same ONCE_CONTROL argument. ONCE_CONTROL must point to a static or
extern variable initialized to PTHREAD_ONCE_INIT.
The initialization functions might throw exception which is why
this function is not marked with __THROW. */
extern int pthread_once (pthread_once_t *__once_control,
void (*__init_routine) (void)) __nonnull ((1, 2));
第一个参数:是和key对应的一个标志,初始化为:PTHREAD_ONCE_INIT
第二个参数:初始化函数
绑定函数:
/* Store POINTER in the thread-specific data slot identified by KEY. */
extern int pthread_setspecific (pthread_key_t __key,
const void *__pointer) __THROW ;
第一个参数:键值key
第二个参数:指向想要绑定的线程数据的指针
获取函数:
/* Return current value of the thread-specific data slot identified by KEY. */
extern void *pthread_getspecific (pthread_key_t __key) __THROW;
参数就是key,返回绑定的线程数据指针
Demo#include
#include
#include
#include
//声明一个全局变量key,该key对所有线程可见,
//但是该key具体指向的内容各个线程不一样
//可以理解为一个二级指针
pthread_key_t key;
//用于标识key,key只创建一次
pthread_once_t once_create = PTHREAD_ONCE_INIT;
//自定义数据结构,用于测试
typedef struct ThreadData_t {
pthread_t m_pid;
char* m_threadName;
} ThreadData;
//释放线程自定义数据,即每个线程使用key具体指向的数据
//这里其实就是ThreadData
static void free_thread_data(void* pData) {
fprintf(stderr, "%s():addr= %p\n", __FUNCTION__, pData);
free(pData);
}
//创建key
static void create_my_key(void) {
fprintf(stderr, "%s():called\n", __FUNCTION__);
pthread_key_create(&key, free_thread_data);
}
static void test_get_thread_data(void) {
ThreadData* pData = (ThreadData*)pthread_getspecific(key);
fprintf(stderr, "%s():%s get data by key addr=%p\n",
__FUNCTION__, pData->m_threadName, pData);
return;
}
//线程函数routine
static void* test_thread(void* thread_name) {
//如果key没有被创建,就创建key,被创建了就不会再创建
pthread_once(&once_create, create_my_key);
//申请一个线程数据结构,该数据只在该线程内可见,其他线程不可见,
//但是该线程的其他函数可以获取到该数据
ThreadData* pData = (ThreadData*)malloc(sizeof(ThreadData));
if (pData == NULL) {
fprintf(stderr, "%s():not enough memory\n", __FUNCTION__);
return NULL;
}
pData->m_pid = pthread_self();
pData->m_threadName = (char*)thread_name;
fprintf(stderr, "thread %s malloc data addr=%p\n",
pData->m_threadName, pData);
pthread_setspecific(key, pData);
sleep(5);
test_get_thread_data();
return NULL;
}
int main(int argc, char** argv) {
pthread_t pid1, pid2;
if (pthread_create(&pid1, NULL, test_thread, (void*)"test thread1") != 0) {
fprintf(stderr, "create thread1 failed\n");
return -1;
}
if (pthread_create(&pid2, NULL, test_thread, (void*)"test thread2") != 0) {
fprintf(stderr, "create thread2 failed\n");
return -1;
}
pthread_join(pid1, NULL);
pthread_join(pid2, NULL);
pthread_key_delete(key);
return 0;
}
执行结果
编译:gcc main.c -o main -lpthread