C 语言互斥锁
外观
C语言互斥锁[编辑 | 编辑源代码]
互斥锁(Mutex,全称 Mutual Exclusion)是C语言多线程编程中用于保护共享资源的核心同步机制。它确保同一时间只有一个线程能访问临界区(Critical Section),从而防止数据竞争(Data Race)和竞态条件(Race Condition)。
基本概念[编辑 | 编辑源代码]
互斥锁的工作原理可类比为「厕所门锁」:
- 线程进入临界区前必须获取锁(锁定)
- 执行完成后释放锁(解锁)
- 其他线程必须等待锁释放才能进入
数学表达为:
POSIX线程库实现[编辑 | 编辑源代码]
C语言通过`pthread_mutex_t`类型实现互斥锁:
#include <pthread.h>
// 声明互斥锁
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
void* thread_func(void* arg) {
pthread_mutex_lock(&mutex); // 加锁
// 临界区代码
pthread_mutex_unlock(&mutex); // 解锁
return NULL;
}
完整示例[编辑 | 编辑源代码]
模拟银行账户转账操作:
#include <stdio.h>
#include <pthread.h>
int balance = 1000; // 共享资源
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
void* transfer(void* amount) {
int amt = *(int*)amount;
pthread_mutex_lock(&mutex);
if(balance >= amt) {
balance -= amt;
printf("转账 %d 成功,余额: %d\n", amt, balance);
} else {
printf("余额不足!\n");
}
pthread_mutex_unlock(&mutex);
return NULL;
}
int main() {
pthread_t t1, t2;
int amount1 = 600, amount2 = 700;
pthread_create(&t1, NULL, transfer, &amount1);
pthread_create(&t2, NULL, transfer, &amount2);
pthread_join(t1, NULL);
pthread_join(t2, NULL);
printf("最终余额: %d\n", balance);
return 0;
}
输出示例:
转账 600 成功,余额: 400 余额不足! 最终余额: 400
互斥锁类型[编辑 | 编辑源代码]
POSIX提供多种互斥锁类型:
类型 | 描述 |
---|---|
PTHREAD_MUTEX_NORMAL | 标准互斥锁(不检测死锁) |
PTHREAD_MUTEX_ERRORCHECK | 错误检查锁(检测递归锁定) |
PTHREAD_MUTEX_RECURSIVE | 可递归锁(允许同一线程多次加锁) |
PTHREAD_MUTEX_DEFAULT | 系统默认类型 |
死锁预防[编辑 | 编辑源代码]
互斥锁使用不当会导致死锁,常见场景:
- 线程A持有锁1请求锁2
- 线程B持有锁2请求锁1
解决方法:
- 固定加锁顺序
- 使用`pthread_mutex_trylock()`
- 设置超时等待
性能考量[编辑 | 编辑源代码]
互斥锁会引入性能开销,优化策略包括:
- 减小临界区范围
- 使用读写锁(`pthread_rwlock_t`)替代
- 考虑无锁编程(Lock-free)方案
实际应用场景[编辑 | 编辑源代码]
1. 数据库连接池:管理有限连接资源 2. GUI事件处理:防止界面更新冲突 3. 游戏引擎:同步物理引擎与渲染线程
状态转换图[编辑 | 编辑源代码]
常见错误[编辑 | 编辑源代码]
- 忘记解锁导致死锁
- 在临界区内调用可能阻塞的函数
- 不同线程以不同顺序获取多个锁
进阶话题[编辑 | 编辑源代码]
- 条件变量(`pthread_cond_t`)与互斥锁配合使用
- 自旋锁(`pthread_spinlock_t`)在短等待时的应用
- C11标准引入的`mtx_t`类型
互斥锁是多线程编程的基础工具,正确使用可以构建线程安全的应用程序,但需要开发者谨慎处理锁的获取和释放顺序。