代码详细注释:演示多线程如何安全操作共享变量,使用互斥锁避免数据竞争。
#include<stdio.h> // 标准输入输出库(用于printf)
#include<pthread.h> // POSIX线程库(用于多线程操作)
#include <semaphore.h> // 信号量库(未直接使用,可删除)int g_val = 0; // 全局共享变量,初始值为0// 定义互斥锁变量,类型为 pthread_mutex_t
pthread_mutex_t mutex; // 用于保护对 g_val 的访问// 线程例程1:线程创建后执行此函数
void* start_routine1(void *arg)
{pthread_mutex_lock(&mutex); // 加锁,进入临界区g_val = 100; // 修改共享变量sleep(1); // 模拟耗时操作(1秒)printf("start_routine1 g_val:%d\n", g_val); // 打印 g_val 的值pthread_mutex_unlock(&mutex); // 解锁,退出临界区pthread_exit(NULL); // 线程退出
} // 线程例程2:线程创建后执行此函数
void* start_routine2(void *arg)
{pthread_mutex_lock(&mutex); // 加锁,进入临界区sleep(1); // 模拟耗时操作(1秒)g_val = 200; // 修改共享变量printf("start_routine2 g_val:%d\n", g_val); // 打印 g_val 的值pthread_mutex_unlock(&mutex); // 解锁,退出临界区pthread_exit(NULL); // 线程退出
} int main()
{// 初始化互斥锁(属性为NULL,使用默认属性)pthread_mutex_init(&mutex, NULL);// 创建子线程1,执行 start_routine1pthread_t thread1;pthread_create(&thread1, NULL, start_routine1, NULL);// 创建子线程2,执行 start_routine2pthread_t thread2;pthread_create(&thread2, NULL, start_routine2, NULL);// 等待子线程1退出(阻塞主线程,直到thread1结束)pthread_join(thread1, NULL); // 等待子线程2退出(阻塞主线程,直到thread2结束)pthread_join(thread2, NULL); return 0; // 主线程退出
}
代码作用详解
共享变量
g_val
全局变量,初始值为
0
,会被两个线程修改。不加锁时,可能因 竞争条件(Race Condition) 导致数据不一致。
互斥锁
mutex
通过
pthread_mutex_lock
和pthread_mutex_unlock
保护临界区。确保同一时间只有一个线程能修改
g_val
。
线程逻辑
thread1
:加锁 →
g_val = 100
→ 休眠 1 秒 → 打印g_val
→ 解锁。
thread2
:加锁 → 休眠 1 秒 →
g_val = 200
→ 打印g_val
→ 解锁。
主线程
初始化锁 → 创建线程 → 等待线程结束 → 退出。
关键点
互斥锁的作用:
防止g_val
被同时修改,保证输出的g_val
是100
或200
,不会出现中间状态。线程执行顺序:
取决于系统调度,但加锁后必然是一个线程执行完临界区,另一个线程才能进入。输出结果:
可能是:text
start_routine1 g_val:100 start_routine2 g_val:200
或
text
start_routine2 g_val:200 start_routine1 g_val:100
但不会出现交叉打印或数据错误。
总结
✅ 功能:
演示多线程如何安全操作共享变量。
使用互斥锁避免数据竞争。
⚠ 注意事项:
锁的粒度要合理,避免性能问题。
确保所有路径都能解锁(如
return
前检查锁状态)。