互斥锁
类似于PV操作。用于同步线程对共享数据的访问。
类型为:pthread_mutex_t
14.5.1 基础API
#include<pthread.h>
//用于初始化互斥锁。若mutexattr为NULL,则表示使用默认属性。
int pthread_mutex_init(pthread_mutex_t* mutex,const pthread_mutexattr_t* mutexattr);
//用于销毁互斥锁,以释放其占用的内核资源。销毁一个已经加锁的互斥锁将导致不可预期的后果。
int pthread_mutex_destroy(pthread_mutex_t* mutex);
//原子操作的方式给一个互斥锁加锁。如果目标互斥锁已经被锁上,则pthread_mutex_lock调用将阻塞
int pthread_mutex_lock(pthread_mutex_t* mutex);
//非阻塞上锁,返回错误码EBUSY
int pthread_mutex_trylock(pthread_mutex_t* mutex);
//以原子操作的方式给一个互斥锁解锁。
int pthread_mutex_unlock(pthread_mutex_t* mutex);
注意:pthread_mutex_lock 和 pthread_mutex_trylock是针对普通锁而言的。
14.5.2 互斥锁属性
类型:pthread_mutexattr_t
#include<pthread.h>
/*初始化互斥锁属性对象*/
int pthread_mutexattr_init(pthread_mutexattr_t* attr);
/*销毁互斥锁属性对象*/
int pthread_mutexattr_destroy(pthread_mutexattr_t* attr);
/*获取和设置互斥锁的pshared属性*/
int pthread_mutexattr_getpshared(const pthread_mutexattr_t* attr,int* pshared);
int pthread_mutexattr_setpshared(pthread_mutexattr_t* attr,int pshared);
/*获取和设置互斥锁的type属性*/
int pthread_mutexattr_gettype(const pthread_mutexattr_t* attr,int* type);
int pthread_mutexattr_settype(pthread_mutexattr_t* attr,int type);
-
pshared:指定是否允许跨进程共享互斥锁
- PTHREAD_PROCESS_SHARED:互斥锁可以被跨进程共享
- PTHREAD_PROCESS_PRIVATE:互斥锁只能被和锁的初始化线程隶属于同一个进程的线程共享。
-
type:互斥锁的类型以及死锁示例
-
PTHREAD_MUTEX_NORMAL:普通锁,默认类型。
当一个线程对一个普通锁加锁以后,其余请求该锁的线程将形成一个等待队列,并在该锁解锁后按优先级获得它。这种锁类型保证了资源分配的公平性。
但这种锁也很容易引发问题:一个线程(A)如果对一个已经加锁(也是由线程A加锁)的普通锁再次加锁,将引发死锁(EG:设计有BUG的递归程序);对一个已经被其他线程加锁的普通锁解锁,或者对一个已经解锁的普通锁再次解锁,将导致不可预期的后果。【注意:这里指的是是同一个线程对mutex多次加锁、解锁;而不是不同线程对一个mutex加锁解锁】 -
PTHREAD_MUTEX_ERRORCHECK:检错锁。
一个线程如果对一个已经加锁的检错锁再次加锁,则加锁操作返回EDEADLK。对一个已经被其他线程加锁的检错锁解锁,或者对一个已经解锁的检错锁再次解锁,则解锁操作返回EPERM。
-
PTHREAD_MUTEX_RECURSIVE:嵌套锁。
这种锁允许一个线程在释放锁之前多次对它加锁而不发生死锁。不过其他线程如果要
获得这个锁,则当前锁的拥有者必须执行相应次数的解锁操作。对一个已经被其他线程加锁的嵌套锁解锁,或者对一个已经解锁的嵌套锁再次解锁,则解锁操作返回EPERM。 -
PTHREAD_MUTEX_DEFAULT:默认锁。
一个线程如果对一个已经加锁的默认锁再次加锁,或者对一个已经被其他线程加锁的默认锁解锁,或者对一个已经解锁的默认锁再次解锁,将导致不可预期的后果。
-