Linux中mutex机制
在Linux中,mutex
是一种用于多线程编程的同步机制,用于保护共享资源,防止多个线程同时访问或修改这些资源,从而避免竞态条件的发生。mutex
是“mutual exclusion”的缩写,意为“互斥”。
1. Mutex 的基本概念
- 互斥锁:
mutex
是一种锁机制,用于确保在任何时刻只有一个线程可以访问共享资源。当一个线程持有mutex
时,其他试图获取该mutex
的线程将被阻塞,直到持有mutex
的线程释放它。 - 临界区:被
mutex
保护的代码段称为“临界区”。在临界区内,线程可以安全地访问共享资源,而不会被其他线程干扰。
2. Linux 中的 Mutex 实现
在Linux中,mutex
通常通过 POSIX 线程库来实现。pthread
提供了一组函数来创建、初始化、锁定、解锁和销毁 mutex
。
2.1 创建和初始化 Mutex
在使用 mutex
之前,需要先创建并初始化它。可以使用 pthread_mutex_init
函数来初始化一个 mutex
。
#include <pthread.h>
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; // 静态初始化
// 或者动态初始化
int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr);
pthread_mutex_t
是mutex
的类型。PTHREAD_MUTEX_INITIALIZER
是用于静态初始化mutex
的宏。pthread_mutex_init
用于动态初始化mutex
,attr
参数可以用来设置mutex
的属性(如类型、优先级等),通常可以传入NULL
使用默认属性。
2.2 锁定 Mutex
线程在进入临界区之前需要先锁定 mutex
,以确保没有其他线程同时进入临界区。可以使用 pthread_mutex_lock
函数来锁定 mutex
。
int pthread_mutex_lock(pthread_mutex_t *mutex);
- 如果
mutex
已经被其他线程锁定,调用pthread_mutex_lock
的线程将被阻塞,直到mutex
被解锁。
2.3 解锁 Mutex
线程在退出临界区之后需要解锁 mutex
,以允许其他线程进入临界区。可以使用 pthread_mutex_unlock
函数来解锁 mutex
。
int pthread_mutex_unlock(pthread_mutex_t *mutex);
2.4 销毁 Mutex
当 mutex
不再需要时,应该销毁它以释放相关资源。可以使用 pthread_mutex_destroy
函数来销毁 mutex
。
int pthread_mutex_destroy(pthread_mutex_t *mutex);
- 销毁
mutex
之前,必须确保没有线程持有该mutex
。
3. Mutex 的使用示例
以下是一个多线程程序,使用 mutex
来保护共享资源。
#include <stdio.h>
#include <pthread.h>
int shared_data = 0;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
void* thread_function(void* arg) {
for (int i = 0; i < 100000; i++) {
pthread_mutex_lock(&mutex); // 锁定 mutex
shared_data++; // 修改共享资源
pthread_mutex_unlock(&mutex); // 解锁 mutex
}
return NULL;
}
int main() {
pthread_t thread1, thread2;
pthread_create(&thread1, NULL, thread_function, NULL);
pthread_create(&thread2, NULL, thread_function, NULL);
pthread_join(thread1, NULL);
pthread_join(thread2, NULL);
printf("Shared data: %d\n", shared_data);
pthread_mutex_destroy(&mutex); // 销毁 mutex
return 0;
}
在这个示例中,两个线程同时递增 shared_data
变量。由于 shared_data
是共享资源,因此使用 mutex
来保护它,确保每次只有一个线程可以修改 shared_data
。
4. Mutex 的类型
在Linux中,pthread_mutex_t
可以有多种类型,通过 pthread_mutexattr_settype
函数可以设置 mutex
的类型。
- PTHREAD_MUTEX_NORMAL:普通
mutex
,不进行死锁检测。如果一个线程重复锁定同一个mutex
,会导致死锁。 - PTHREAD_MUTEX_RECURSIVE:递归
mutex
,允许同一个线程多次锁定同一个mutex
。每次锁定操作必须对应一次解锁操作。 - PTHREAD_MUTEX_ERRORCHECK:错误检查
mutex
,如果一个线程重复锁定同一个mutex
,会返回错误而不是导致死锁。