设计思路
- 双重检查锁定(Double-Checked Locking):在访问
globalPtr
前,先进行一次无锁的NULL检查。如果指针不为NULL,直接使用;若为NULL,则获取锁,再次检查并处理。
- 原子操作:使用原子操作函数来确保对指针的读写是原子性的,减少锁的使用频率。
- 初始化策略:在程序启动时,确保
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;
}
代码说明
_Atomic(int*) globalPtr
:声明一个原子类型的全局指针,保证对其读写的原子性。
initGlobalPtr
函数:在程序启动时初始化globalPtr
,确保其不为NULL。
threadFunction
函数:线程入口函数,先进行无锁的NULL检查,若为NULL则获取锁再次检查并初始化。
main
函数:创建线程并等待其结束,最后清理资源。