面试题答案
一键面试线程局部存储(TLS)清理的基本原理
线程局部存储(TLS)允许每个线程拥有独立的数据副本。当一个线程终止时,TLS 机制会自动调用为该线程的 TLS 数据设置的清理函数。这确保了每个线程独有的资源,如动态分配的内存等,可以被正确释放,避免内存泄漏。其原理基于操作系统对线程生命周期的管理,在检测到线程即将终止时,遍历该线程的 TLS 数据区域,调用相应的清理函数。
简单代码示例
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
// 定义一个线程局部存储的键
__thread int *tls_data;
// 清理函数
void cleanup(void *arg) {
printf("Cleaning up thread local data\n");
free(arg);
}
void* thread_function(void* arg) {
// 为线程局部存储分配内存
tls_data = (int *)malloc(sizeof(int));
if (tls_data == NULL) {
perror("malloc");
return NULL;
}
*tls_data = 42;
// 设置清理函数
pthread_cleanup_push(cleanup, tls_data);
// 线程执行的其他代码
printf("Thread %ld: tls_data = %d\n", (long)pthread_self(), *tls_data);
pthread_cleanup_pop(1); // 1 表示执行清理函数
return NULL;
}
int main() {
pthread_t thread;
if (pthread_create(&thread, NULL, thread_function, NULL) != 0) {
perror("pthread_create");
return 1;
}
if (pthread_join(thread, NULL) != 0) {
perror("pthread_join");
return 1;
}
return 0;
}
在上述代码中:
__thread int *tls_data;
定义了一个线程局部存储变量tls_data
。cleanup
函数是清理函数,用于释放tls_data
指向的内存。pthread_cleanup_push(cleanup, tls_data);
将清理函数cleanup
与tls_data
关联,当线程终止时会调用该清理函数。pthread_cleanup_pop(1);
中的参数1
表示线程正常结束时执行清理函数,如果为0
则不执行清理函数。