MST

星途 面试题库

面试题:C语言中多线程环境下NULL指针的安全检查与优化

在多线程C语言程序中,有一个共享的全局指针`int *globalPtr`,多个线程会对其进行读写操作。请设计一套完整的机制,不仅要对`globalPtr`进行NULL指针安全检查,还要考虑多线程竞争访问的情况,确保在任何情况下都不会因为NULL指针导致程序崩溃,并且尽可能优化性能,减少锁带来的开销。描述设计思路并给出关键代码片段。
25.0万 热度难度
编程语言C

知识考点

AI 面试

面试题答案

一键面试

设计思路

  1. 双重检查锁定(Double-Checked Locking):在访问globalPtr前,先进行一次无锁的NULL检查。如果指针不为NULL,直接使用;若为NULL,则获取锁,再次检查并处理。
  2. 原子操作:使用原子操作函数来确保对指针的读写是原子性的,减少锁的使用频率。
  3. 初始化策略:在程序启动时,确保globalPtr被正确初始化,避免初始状态为NULL。

关键代码片段

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

// 共享的全局指针
_Atomic(int*) globalPtr = NULL;
pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;

// 初始化函数
void initGlobalPtr() {
    int *newPtr = (int*)malloc(sizeof(int));
    if (newPtr) {
        *newPtr = 42;
        atomic_store(&globalPtr, newPtr);
    }
}

// 线程函数
void* threadFunction(void* arg) {
    int *localPtr = atomic_load(&globalPtr);
    if (!localPtr) {
        pthread_mutex_lock(&lock);
        localPtr = atomic_load(&globalPtr);
        if (!localPtr) {
            initGlobalPtr();
            localPtr = atomic_load(&globalPtr);
        }
        pthread_mutex_unlock(&lock);
    }
    if (localPtr) {
        printf("Thread accessed globalPtr: %d\n", *localPtr);
    }
    return NULL;
}

int main() {
    pthread_t thread1, thread2;

    // 初始化全局指针
    initGlobalPtr();

    // 创建线程
    pthread_create(&thread1, NULL, threadFunction, NULL);
    pthread_create(&thread2, NULL, threadFunction, NULL);

    // 等待线程结束
    pthread_join(thread1, NULL);
    pthread_join(thread2, NULL);

    // 清理
    pthread_mutex_destroy(&lock);
    int *tmp = atomic_exchange(&globalPtr, NULL);
    if (tmp) {
        free(tmp);
    }

    return 0;
}

代码说明

  1. _Atomic(int*) globalPtr:声明一个原子类型的全局指针,保证对其读写的原子性。
  2. initGlobalPtr函数:在程序启动时初始化globalPtr,确保其不为NULL。
  3. threadFunction函数:线程入口函数,先进行无锁的NULL检查,若为NULL则获取锁再次检查并初始化。
  4. main函数:创建线程并等待其结束,最后清理资源。