多线程互斥-Mutex
目录
- 同步和互斥
- 互斥锁机制
- 互斥锁基本编程
- 读写锁机制
- 相关函数
同步和互斥
互斥:是指某一资源同时只允许一个访问者对其进行访问,具有唯一性和排它性。但互斥无法限制访问者对资源的访问顺序,即访问是无序的。
同步:是指在互斥的基础上(大多数情况),通过其它机制实现访问者对资源的有序访问。
互斥锁机制
互斥锁是用一种简单的加锁方法来控制对共享资源的访问,互斥锁有两种状态,上锁和解锁,可以把互斥锁看作成某种意义上的全局变量。在同一时刻只能有一个线程掌握这个互斥锁,拥有上锁状态的线程能够对共享资源按照顺序进行操作。若其他线程希望上锁一个已经被上锁的互斥锁,则该线程会被挂起,直到互斥锁被上锁的线程释放(解锁)。
互斥锁的基本操作
1.初始化互斥锁
一般由主线程来初始化一个互斥锁,有动态和静态两种初始化方式 具体实现:
静态:pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; 动态: pthread_mutex_init 函数
2.申请互斥锁(上锁)
在访问共享资源前,首先申请互斥锁,如果互斥锁处于开锁状态,则就可以申请到,并立即占有这个该互斥锁。以防止其他线程访问该资源。
具体实现: pthread_mutex_lock 函数
3.释放互斥锁 (解锁)
具体实现: pthread_mutex_unlock 函数
4.销毁互斥锁
具体实现 pthread_mutex_destroy函数
互斥锁相关函数
函数 | pthread_mutex_init |
---|---|
头文件 | #include < pthread.h> |
函数原型 | int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr); |
功能 | 初始化一个互斥锁。 |
参数 | 1.mutex:需初始化的互斥锁; 2.attr:互斥锁的属性,如果为NULL,默认属性为快速互斥锁。 attr 取值可以为以下3种:PTHREAD_MUTEX_INITIALIZER: 快速互斥锁PTHREAD_RECURSIVE_MUTEX_INITIALIZER_UP: 递归互斥锁PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_UP: 检错互斥锁 |
返回值 | 成功:返回0;失败:返回错误号。 |
函数 | pthread_mutex_lock |
---|---|
头文件 | #include < pthread.h> |
函数原型 | int pthread_mutex_lock(pthread_mutex_t *mutex ); |
功能 | 上锁一个互斥锁。若互斥锁已经被锁定,则线程阻塞,直到该互斥锁变为可用为止 |
参数 | mutex:互斥锁; |
返回值 | 成功:返回0;失败:返回错误号。 |
函数 | pthread_mutex_unlock |
---|---|
头文件 | #include < pthread.h> |
函数原型 | int pthread_mutex_unlock(pthread_mutex_t* mutex ); |
功能 | 解锁一个互斥锁。 |
参数 | 1.mutex:互斥锁; |
返回值 | 成功:返回0;失败:返回错误号。 |
函数 | pthread_mutex_destroy |
---|---|
头文件 | #include < pthread.h> |
函数原型 | int pthread_mutex_destroy(pthread_mutex_t *mutex); |
功能 | 销毁一个互斥锁,即意味着释放它所占用的资源,且要求锁当前处于开放状态。 |
参数 | mutex:需要被释放的锁变量对象。 |
返回值 | 成功:返回0;失败:返回错误号。 |
读写锁(rwlock机制)
我们对共享资源的访问,往往存在两种方式,向共享资源写入数据,或从共享资源中获取数据,写操作对数据来说往往是不安全的,而读操作是安全的。 如果线程间采用所有操作都独占的方式,势必会引起资源访问的效率问题。
读写锁与互斥量类似可以实现线程对临界资源的互斥访问,但和互斥量不同的是:互斥量对临界资源的访问是独占的方式;然而读写锁会视对临界资源的具体访问方式来决定是独占还是共享的方式来访问。
相对互斥量只有加锁和不加锁两种状态,读写锁有三种状态:读模式下的加锁,写模式下的加锁,不加锁。
读写锁的使用规则:
- 只要没有写模式下的加锁,任意线程都可以进行读模式下的加锁; 只有读写锁处于不加锁状态时,才能进行写模式下的加锁;
- 读写锁也称为共享-独占(shared-exclusive)锁,当读写锁以读模式加锁时,它是以共享模式锁住,当以写模式加锁时,它是以独占模式锁住。读写锁非常适合读数据的频率远大于写数据的频率的应用中。这样可以在任何时刻运行多个读线程并发的执行,给程序带来了更高的并发度。
读写锁的基本操作
1.初始化读写锁
静态:pthread_rwlock_t mutex = PTHREAD_RWLOCK_INITIALIZER; 动态: pthread_rwlock_init 函数
2.写模式上锁
在以写的方式访问共享资源前,首先申请写模式上锁锁
具体实现: pthread_rwlock_wrlock 函数
3.读模式上锁
在以读的方式访问共享资源前,首先申请读模式上锁锁
具体实现: pthread_rwlock_rdlock 函数
4.释放互斥锁 (解锁)
具体实现: pthread_rwlock_unlock 函数
5.销毁互斥锁
具体实现 pthread_rwlock_destroy函数
读写锁的相关函数
函数 | pthread_rwlock_init |
---|---|
头文件 | #include < pthread.h> |
函数原型 | int pthread_rwlock_init(pthread_rwlock_t *rwlock, const pthread_rwlockattr_t *attr); |
功能 | 初始化一个读写锁。 |
参数 | 1.rwlock:需初始化的读写锁; 2.attr:读写锁的属性,通常为NULL。 |
返回值 | 成功:返回0; 失败:返回错误号。 |
函数 | pthread_rwlock_rdlock |
---|---|
头文件 | #include < pthread.h> |
函数原型 | int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock ); |
功能 | 对读写锁读模式上锁。 |
参数 | rwlock:指向读写锁的指针 |
返回值 | 成功:返回0; 失败:返回错误号。 |
函数 | pthread_rwlock_wrlock |
---|---|
头文件 | #include < pthread.h> |
函数原型 | int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock ); |
功能 | 对读写锁写模式上锁。 |
参数 | rwlock:指向读写锁的指针 |
返回值 | 成功:返回0; 失败:返回错误号。 |
函数 | pthread_rwlock_unlock |
---|---|
头文件 | #include < pthread.h> |
函数原型 | int pthread_rwlock_unlock(pthread_rwlock_t *rwlock ); |
功能 | 对读写锁解锁。 |
参数 | rwlock:指向读写锁的指针 |
返回值 | 成功:返回0; 失败:返回错误号。 |
函数 | pthread_rwlock_destroy |
---|---|
头文件 | #include < pthread.h> |
函数原型 | int pthread_rwlock_destroy(pthread_rwlock_t *rwlock ); |
功能 | 销毁读写锁。 |
参数 | rwlock:指向读写锁的指针 |
返回值 | 成功:返回0; 失败:返回错误号。 |