MST
星途 面试题库

面试题:C语言Linux线程局部存储的复杂场景应用

在一个多线程的Linux C程序中,有多个不同功能的线程,每个线程都需要使用线程局部存储来管理一些动态分配的内存资源(例如,每个线程需要自己的一个字符串数组,其大小在运行时确定)。请设计一个合理的结构体来管理这些线程局部存储资源,并编写代码实现资源的初始化、使用和释放,同时要考虑内存泄漏等问题。
28.8万 热度难度
编程语言C

知识考点

AI 面试

面试题答案

一键面试
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>

// 定义用于线程局部存储的结构体
typedef struct {
    char **stringArray;
    int arraySize;
} ThreadLocalData;

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

// 线程局部存储的析构函数,用于释放内存
void freeThreadLocalData(void *data) {
    ThreadLocalData *threadData = (ThreadLocalData *)data;
    if (threadData) {
        for (int i = 0; i < threadData->arraySize; i++) {
            free(threadData->stringArray[i]);
        }
        free(threadData->stringArray);
        free(threadData);
    }
}

// 线程执行函数
void* threadFunction(void* arg) {
    // 获取线程局部存储数据
    ThreadLocalData *threadData = (ThreadLocalData *)pthread_getspecific(key);
    if (!threadData) {
        // 初始化线程局部存储数据
        threadData = (ThreadLocalData *)malloc(sizeof(ThreadLocalData));
        if (!threadData) {
            perror("malloc");
            pthread_exit(NULL);
        }
        // 假设动态确定数组大小为10
        threadData->arraySize = 10;
        threadData->stringArray = (char **)malloc(threadData->arraySize * sizeof(char *));
        if (!threadData->stringArray) {
            perror("malloc");
            free(threadData);
            pthread_exit(NULL);
        }
        for (int i = 0; i < threadData->arraySize; i++) {
            threadData->stringArray[i] = (char *)malloc(100 * sizeof(char));
            if (!threadData->stringArray[i]) {
                perror("malloc");
                for (int j = 0; j < i; j++) {
                    free(threadData->stringArray[j]);
                }
                free(threadData->stringArray);
                free(threadData);
                pthread_exit(NULL);
            }
            snprintf(threadData->stringArray[i], 100, "Thread %ld String %d", pthread_self(), i);
        }
        // 设置线程局部存储数据
        pthread_setspecific(key, threadData);
    }

    // 使用线程局部存储数据
    for (int i = 0; i < threadData->arraySize; i++) {
        printf("Thread %ld: %s\n", pthread_self(), threadData->stringArray[i]);
    }

    pthread_exit(NULL);
}

int main() {
    // 初始化线程局部存储键
    if (pthread_key_create(&key, freeThreadLocalData) != 0) {
        perror("pthread_key_create");
        return 1;
    }

    // 创建多个线程
    pthread_t threads[5];
    for (int i = 0; i < 5; i++) {
        if (pthread_create(&threads[i], NULL, threadFunction, NULL) != 0) {
            perror("pthread_create");
            return 1;
        }
    }

    // 等待所有线程结束
    for (int i = 0; i < 5; 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. 结构体定义
    • 定义了ThreadLocalData结构体,包含一个char **类型的stringArray用于存储字符串数组,以及一个int类型的arraySize表示数组大小。
  2. 线程局部存储键和析构函数
    • 使用pthread_key_t类型的变量key作为线程局部存储键。
    • freeThreadLocalData函数作为析构函数,用于在每个线程退出时释放动态分配的内存,避免内存泄漏。
  3. 线程执行函数
    • threadFunction函数首先通过pthread_getspecific获取线程局部存储数据。
    • 如果数据未初始化,则动态分配内存来初始化stringArray并填充字符串。
    • 然后使用这些字符串,最后线程退出时,析构函数会自动释放内存。
  4. 主函数
    • main函数中,首先使用pthread_key_create创建线程局部存储键,并指定析构函数。
    • 接着创建多个线程,每个线程执行threadFunction
    • 等待所有线程结束后,使用pthread_key_delete删除线程局部存储键。