MST
星途 面试题库

面试题:C语言中线程局部存储(TLS)的基本原理及简单应用

请简述Linux C语言中线程局部存储机制的基本原理。并给出一个简单的代码示例,展示如何使用线程局部存储来存储每个线程独有的数据。
13.8万 热度难度
编程语言C

知识考点

AI 面试

面试题答案

一键面试

线程局部存储机制基本原理

线程局部存储(Thread Local Storage,TLS)是一种线程相关的数据存储机制。在多线程编程环境下,每个线程都有自己独立的地址空间,TLS 允许每个线程拥有一份独立的变量实例,这些变量对于其他线程是不可见的。这样不同线程对相同变量名的操作不会相互干扰,保证了线程数据的独立性和安全性。

当线程启动时,系统为线程局部存储变量分配空间,并进行初始化。在线程运行过程中,对这些变量的访问都是针对该线程自己的那份实例。当线程终止时,对应的线程局部存储变量的存储空间会被释放。

代码示例

#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>

// 定义线程局部存储键
static pthread_key_t key;

// 线程清理函数
static void destructor(void *arg) {
    printf("Thread %lu is cleaning up\n", (unsigned long)pthread_self());
    free(arg);
}

// 线程执行函数
void* thread_function(void* arg) {
    // 为每个线程分配独立的内存空间
    int *thread_specific_data = (int*)malloc(sizeof(int));
    if (thread_specific_data == NULL) {
        perror("malloc");
        pthread_exit(NULL);
    }
    // 设置线程局部存储数据
    *thread_specific_data = *((int*)arg);
    // 将数据与线程局部存储键关联
    pthread_setspecific(key, thread_specific_data);

    printf("Thread %lu set its data to %d\n", (unsigned long)pthread_self(), *thread_specific_data);

    // 模拟一些工作
    sleep(1);

    // 获取线程局部存储数据
    int *retrieved_data = (int*)pthread_getspecific(key);
    printf("Thread %lu retrieved its data: %d\n", (unsigned long)pthread_self(), *retrieved_data);

    return NULL;
}

int main() {
    // 创建线程局部存储键
    if (pthread_key_create(&key, destructor) != 0) {
        perror("pthread_key_create");
        return 1;
    }

    pthread_t threads[3];
    int data[3] = {10, 20, 30};

    // 创建线程
    for (int i = 0; i < 3; i++) {
        if (pthread_create(&threads[i], NULL, thread_function, &data[i]) != 0) {
            perror("pthread_create");
            return 1;
        }
    }

    // 等待所有线程完成
    for (int i = 0; i < 3; i++) {
        if (pthread_join(threads[i], NULL) != 0) {
            perror("pthread_join");
            return 1;
        }
    }

    // 删除线程局部存储键
    if (pthread_key_delete(key) != 0) {
        perror("pthread_key_delete");
        return 1;
    }

    return 0;
}

在上述代码中:

  1. 使用 pthread_key_create 创建一个线程局部存储键 key,并指定了清理函数 destructor
  2. 每个线程在 thread_function 中,使用 malloc 分配独立的内存,并将其与 key 关联,设置和获取数据。
  3. main 函数创建多个线程,并等待它们完成,最后删除线程局部存储键。清理函数 destructor 在线程结束时释放每个线程分配的内存。