互斥量(Mutex,全称 Mutual Exclusion)用于保证同一时间只有一个线程(或进程)访问共享资源,从而避免并发操作导致的数据不一致问题
在 Linux 中,互斥量(Mutex,全称 Mutual Exclusion) 是一种用于多线程(或多进程)同步的机制,用于保证同一时间只有一个线程(或进程)访问共享资源,从而避免并发操作导致的数据不一致问题。
互斥量的核心思想是"独占访问":当一个线程持有互斥量时,其他线程必须等待该线程释放互斥量后才能获取,以此实现对共享资源的安全访问。
互斥量的核心特性
- 互斥性:同一时间只能有一个线程持有互斥量(获得锁),其他线程尝试获取时会阻塞等待。
- 原子性:获取和释放互斥量的操作是原子的(不可分割),不会被其他线程打断。
- 所有权:互斥量具有"所有权"属性,只有持有它的线程才能释放它(避免其他线程误释放)。
- 阻塞/非阻塞模式:支持阻塞等待(获取不到锁时休眠)和非阻塞模式(获取不到锁时立即返回错误)。
线程互斥量(pthread_mutex_t)
Linux 中最常用的是 POSIX 线程库(pthread) 提供的线程互斥量,通过 pthread_mutex_t
类型实现,主要用于同一进程内的多线程同步。
基本操作函数
函数 | 功能描述 |
---|---|
pthread_mutex_init | 初始化互斥量 |
pthread_mutex_lock | 获取互斥量(阻塞模式,获取不到则等待) |
pthread_mutex_trylock | 尝试获取互斥量(非阻塞模式,失败立即返回) |
pthread_mutex_unlock | 释放互斥量 |
pthread_mutex_destroy | 销毁互斥量,释放资源 |
示例代码:线程互斥量的使用
#include <stdio.h>
#include <pthread.h>int shared_count = 0; // 共享资源
pthread_mutex_t mutex; // 互斥量// 线程函数:安全地递增共享变量
void *increment_count(void *arg) {for (int i = 0; i < 10000; i++) {// 获取互斥量(加锁)pthread_mutex_lock(&mutex);shared_count++; // 临界区:操作共享资源// 释放互斥量(解锁)pthread_mutex_unlock(&mutex);}return NULL;
}int main() {pthread_t tid1, tid2;// 初始化互斥量pthread_mutex_init(&mutex, NULL);// 创建两个线程同时操作共享变量pthread_create(&tid1, NULL, increment_count, NULL);pthread_create(&tid2, NULL, increment_count, NULL);// 等待线程结束pthread_join(tid1, NULL);pthread_join(tid2, NULL);// 销毁互斥量pthread_mutex_destroy(&mutex);printf("最终结果:%d(预期 20000)\n", shared_count);return 0;
}
说明:
- 若不使用互斥量,两个线程同时修改
shared_count
可能导致结果小于 20000(竞态条件)。 - 加锁后,
shared_count++
操作被保护为"原子操作",确保结果正确。
进程互斥量(跨进程互斥)
除了线程间,互斥量也可用于多进程同步(如多个进程访问共享内存时)。实现方式是将互斥量放在共享内存中,并通过初始化属性指定为跨进程共享。
关键步骤
- 创建共享内存,用于存放互斥量。
- 初始化互斥量时,设置
PTHREAD_PROCESS_SHARED
属性,允许跨进程访问。
// 进程间互斥量初始化示例
pthread_mutexattr_t attr;
pthread_mutexattr_init(&attr);
// 设置互斥量可跨进程共享
pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_SHARED);
// 在共享内存中初始化互斥量
pthread_mutex_init(&mutex, &attr);
互斥量的类型(属性)
通过 pthread_mutexattr_settype
可设置互斥量类型,适应不同场景:
PTHREAD_MUTEX_DEFAULT
:默认类型,不提供死锁检测,解锁非自己持有的互斥量会导致未定义行为。PTHREAD_MUTEX_NORMAL
:与默认类型类似,不做错误检查。PTHREAD_MUTEX_ERRORCHECK
:提供错误检查(如解锁未持有或未初始化的互斥量时返回错误),性能略低。PTHREAD_MUTEX_RECURSIVE
:递归互斥量,允许同一线程多次加锁(需对应次数的解锁),避免线程自己死锁。
互斥量 vs 其他同步机制
机制 | 特点对比 | 适用场景 |
---|---|---|
互斥量 | 独占访问,有所有权,支持递归(特定类型) | 线程/进程间共享资源的互斥访问 |
信号量 | 计数器模式,允许多个线程同时访问 | 限制资源访问数量(如连接池) |
读写锁 | 区分读写操作,读共享、写独占 | 读多写少的场景 |
互斥量是最基础、最常用的同步工具,尤其适合"同一时间只允许一个执行者"的场景(如修改全局变量、操作链表等)。
总结
Linux 中的互斥量是保证共享资源安全访问的核心机制,通过"加锁-操作-解锁"的流程,强制线程串行化访问临界区,避免竞态条件。线程互斥量(pthread_mutex_t
)用于进程内同步,而通过共享内存和属性配置,也可实现跨进程同步。合理使用互斥量是编写正确多线程/多进程程序的基础。