互斥锁、自旋锁和读写锁

一、互斥锁

对于多线程的程序,访问冲突的问题是很普遍的,解决的办法是引入互斥锁(Mutex,MutualExclusive Lock),获得锁的线程可以完成“读-修改-写”的操作,然后释放锁给其它线程,没有获得锁的线程只能等待而不能访问共享数据,这样“读-修改-写”三步操作组成一个原子操作,要么都执行,要么都不执行,不会执行到中间被打断,也不会在其它处理器上并行做这个操作。

Mutex用pthread_mutex_t类型的变量表示,pthread_mutex_init函数对Mutex做初始化,参数attr设定Mutex的属性,如果attr为NULL则表示缺省属性,具体看结构体:

 C++ Code 
1
2
3
4
5
6
7
8
9
10
 
struct pthread_mutexattr_t
{
     enum lock_type     // 使用pthread_mutexattr_settype来更改
    {
         PTHREAD_MUTEX_TIMED_NP [ default] //当一个线程加锁后,其余请求锁的线程形成等待队列,在解锁后按优先级获得锁。
         PTHREAD_MUTEX_ADAPTIVE_NP        // 动作最简单的锁类型,解锁后所有线程重新竞争。
         PTHREAD_MUTEX_RECURSIVE_NP       // 允许同一线程对同一锁成功获得多次。当然也要解锁多次。其余线程在解锁时重新竞争。
         PTHREAD_MUTEX_ERRORCHECK_NP      // 若同一线程请求同一锁,返回EDEADLK,否则与PTHREAD_MUTEX_TIMED_NP动作相同。
    } type;
} attr;

用pthread_mutex_init函数初始化的Mutex可以用pthread_mutex_destroy销毁。如果Mutex变量是静态分配的(全局变量或static变量),也可以用宏定义PTHREAD_MUTEX_INITIALIZER来初始化,相当于用pthread_mutex_init初始化并且attr参数为NULL。

一个线程可以调用pthread_mutex_lock获得Mutex,如果这时另一个线程已经调用pthread_mutex_lock获得了该Mutex,则当前线程需要挂起等待,直到另一个线程调用pthread_mutex_unlock释放Mutex,当前线程被唤醒,才能获得该Mutex并继续执行。

上面的具体函数可以man 一下。


二、自旋锁和读写锁简介

(一)、自旋锁

自旋锁类似于互斥锁,它的性能比互斥锁更高。
自旋锁与互斥锁很重要的一个区别在于,线程在申请自旋锁的时候,线程不会被挂起,它处于忙等待的状态,一般用于等待时间比较短的情形。
pthread_spin_init
pthread_spin_destroy
pthread_spin_lock
pthread_spin_unlock

(二)、读写锁

1、只要没有线程持有给定的读写锁用于写,那么任意数目的线程可以持有读写锁用于读。
2、仅当没有线程持有某个给定的读写锁用于读或用于写时,才能分配读写锁用于写。
3、读写锁用于读称为共享锁,读写锁用于写称为排它锁。
pthread_rwlock_init
pthread_rwlock_destroy
int pthread_rwlock_rdlock
int pthread_rwlock_wrlock
int pthread_rwlock_unlock


更多有关linux中的锁问题可以参考这篇文章 :《透过Linux内核看无锁编程》

http://www.ibm.com/developerworks/cn/linux/l-cn-lockfree/


你可能感兴趣的:(LINUX,程序员,操作系统,C/C++)