linux mutex相关函数介绍

linux 互斥锁(mutex)详细说明
typedef union
{
  struct
  {
    int __lock;//lock操作的变量
    unsigned int __count;//lock次数
    int __owner;//thread ID
    
    int __kind; //互斥锁类型
    unsigned int __nusers;  
    int __spins;
  } __data;
  char __size[__SIZEOF_PTHREAD_MUTEX_T];
  long int __align;
} pthread_mutex_t;


typedef union
{
  char __size[__SIZEOF_PTHREAD_MUTEXATTR_T];
  long int __align;
} pthread_mutexattr_t;


一、互斥锁的创建
  锁的创建氛围静态创建和动态创建。
  所谓静态创建就是用宏PTHREAD_MUTEX_INITIALIZER来初始化锁,如:
  prhread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
  动态创建用函数 int pthread_mutex_init(pthread_mutex_t *mutex, const
pthread_mutexattr_t * attr);
参数说明:参数一:mutex为互斥量变量
 参数二:attr为互斥量属性
二、互斥锁的销毁
int pthread_mutex_destroy(pthread_mutex_t *mutex);
销毁互斥锁变量(即释放锁占的资源),且要求当前锁处于开锁状态。在Linux中,互斥
锁并不占用资源,因此,pthread_mutex_destroy()除了检查锁状态以外(锁定状态则返回EBUSY)没有其他动作。
参数说明:mutex为互斥量变量
三、锁的操作
int pthread_mutex_lock(pthread_mutex_t *mutex);加锁
int pthread_mutex_unlock(pthread_mutex_t *mutex);释放锁
int pthread_mutex_trylock(pthread_mutex_t *mutex);加锁
pthread_mutex_trylock()语义与pthread_mutex_lock()类似,不同的是在锁已经被占据时返回EBUSY而不是挂起等待
四、锁的属性
int pthread_mutexattr_init(pthread_mutexattr_t *attr);
互斥锁属性的初始化
int pthread_mutexattr_destroy(pthread_mutexattr_t *attr);
互斥锁属性的销毁,之后,该互斥锁属性回到初始化以前的状态


int pthread_mutexattr_setpshared(const pthread_mutexattr_t* attr,int pshared);
函数说明:设置互斥锁是否进程共享
参数说明:参数一:互斥锁属性变量
 参数二:决定互斥锁是否进程共享
pshared有两个取值:
PTHREAD_PROCESS_SHARED和 PTHREAD_PROCESS_PRIVATE
如果互斥锁属性对象的pshared属性被置PTHREAD_PROCESS_SHARED。
   那么由这个属性对象创建的互斥锁将被保存在共享内存中,可以被多个进程中的
   线程共享。如果pshared属性被置为PTHREAD_PROCESS_PRIVATE,那么只有和
   创建这个互斥锁的线程在同一个进程中的线程才能访问这个互斥锁。
int pthread_mutexattr_getpshared(const pthread_mutexattr_t* attr,int* pshared);
获取指定互斥锁属性变量的共享属性值,存在pshared里。


int pthread_mutexattr_settype (pthread_mutexattr_t * attr, in tkind);
设置互斥锁属性的类型
类型属性的缺省值为 PTHREAD_MUTEX_DEFAULT。
type 参数指定互斥锁的类型。以下列出了有效的互斥锁类型:


PTHREAD_MUTEX_NORMAL
描述:
此类型的互斥锁不会检测死锁。如果线程在不首先解除互斥锁的情况下尝试重新锁定该互斥锁,则会产生死锁。尝试解除由其他线程锁定的互斥锁会产生不确定的行为。如果尝试解除锁定的互斥锁未锁定,则会产生不确定的行为。


PTHREAD_MUTEX_ERRORCHECK
描述:
此类型的互斥锁可提供错误检查。如果线程在不首先解除锁定互斥锁的情况下尝试重新锁定该互斥锁,则会返回错误。如果线程尝试解除锁定的互斥锁已经由其他线程锁定,则会返回错误。如果线程尝试解除锁定的互斥锁未锁定,则会返回错误。


PTHREAD_MUTEX_RECURSIVE
描述:
如果线程在不首先解除锁定互斥锁的情况下尝试重新锁定该互斥锁,则可成功锁定该互斥锁。 与 PTHREAD_MUTEX_NORMAL 类型的互斥锁不同,对此类型互斥锁进行重新锁定时不会产生死锁情况。多次锁定互斥锁需要进行相同次数的解除锁定才可以释放该锁,然后其他线程才能获取该互斥锁。如果线程尝试解除锁定的互斥锁已经由其他线程锁定,则会返回错误。 如果线程尝试解除锁定的互斥锁未锁定,则会返回错误。


PTHREAD_MUTEX_DEFAULT
描述:
如果尝试以递归方式锁定此类型的互斥锁,则会产生不确定的行为。对于不是由调用线程锁定的此类型互斥锁,如果尝试对它解除锁定,则会产生不确定的行为。对于尚未锁定的此类型互斥锁,如果尝试对它解除锁定,也会产生不确定的行为。允许在实现中将该互斥锁映射到其他互斥锁类型之一。对于 Solaris 线程,PTHREAD_PROCESS_DEFAULT 会映射到 PTHREAD_PROCESS_NORMAL。


int pthread_mutexattr_gettype(pthread_mutexattr_t  *attr , int  *type);
获取互斥锁属性的类型,有:
PTHREAD_MUTEX_NORMAL
PTHREAD_MUTEX_ERRORCHECK
PTHREAD_MUTEX_RECURSIVE
PTHREAD_MUTEX_DEFAULT


int pthread_mutexattr_setprotocol(pthread_mutexattr_t *attr, int protocol);
设置互斥锁属性的协议
protocol的值得选择:
PTHREAD_PRIO_NONE
线程的优先级和调度不会受到互斥锁拥有权的影响。
PTHREAD_PRIO_INHERIT
此协议值(如 thrd1)会影响线程的优先级和调度。如果更高优先级的线程因 thrd1 所拥有的一个或多个互斥锁而被阻塞,而这些互斥锁是用 PTHREAD_PRIO_INHERIT 初始化的,则 thrd1 将以高于它的优先级或者所有正在等待这些互斥锁(这些互斥锁是 thrd1 指所拥有的互斥锁)的线程的最高优先级运行。
如果 thrd1 因另一个线程 (thrd3) 拥有的互斥锁而被阻塞,则相同的优先级继承效应会以递归方式传播给 thrd3。
使用 PTHREAD_PRIO_INHERIT 可以避免优先级倒置。低优先级的线程持有较高优先级线程所需的锁时,便会发生优先级倒置。只有在较低优先级的线程释放该锁之后,较高优先级的线程才能继续使用该锁。设置 PTHREAD_PRIO_INHERIT,以便按与预期的优先级相反的优先级处理每个线程。
PTHREAD_PRIO_PROTECT
当线程拥有一个或多个使用 PTHREAD_PRIO_PROTECT 初始化的互斥锁时,此协议值会影响其线程(如 thrd2)的优先级和调度。thrd2 以其较高的优先级或者以 thrd2 拥有的所有互斥锁的最高优先级上限运行。基于被 thrd2 拥有的任一互斥锁阻塞的较高优先级线程对于 thrd2 的调度没有任何影响。
int pthread_mutexattr_getprotocol(const pthread_mutexattr_t *attr,int*
protocol);
获取互斥锁属性的协议


int pthread_mutexattr_setprioceiling(pthread_mutexatt_t *attr,int prioceiling, int *oldceiling);
attr 指示以前调用 pthread_mutexattr_init() 时创建的互斥锁属性对象。
prioceiling 指定已初始化互斥锁的优先级上限。优先级上限定义执行互斥锁保护的临界段时的最低优先级。prioceiling 位于 SCHED_FIFO 所定义的优先级的最大范围内。要避免优先级倒置,请将 prioceiling 设置为高于或等于可能会锁定特定互斥锁的所有线程的最高优先级。
oldceiling 包含以前的优先级上限值。
int pthread_mutexattr_getprioceiling(const pthread_mutexatt_t *attr, int *prioceiling);
获取互斥锁属性的优先级上限


int pthread_mutex_setprioceiling(pthread_mutex_t *mutex, int prioceiling, int *old_ceiling);
pthread_mutex_setprioceiling() 可更改互斥锁 mutex 的优先级上限 prioceiling。 pthread_mutex_setprioceiling() 可锁定互斥锁(如果未锁定的话),或者一直处于阻塞状态,直到 pthread_mutex_setprioceiling() 成功锁定该互斥锁,更改该互斥锁的优先级上限并将该互斥锁释放为止。锁定互斥锁的过程无需遵循优先级保护协议。
如果 pthread_mutex_setprioceiling() 成功,则将在 old_ceiling 中返回以前的优先级上限值。如果pthread_mutex_setprioceiling() 失败,则互斥锁的优先级上限保持不变。
int pthread_mutex_getprioceiling(const pthread_mutex_t *mutex, int *prioceiling);
获取互斥锁 的优先级上限 prioceiling。


int pthread_mutexattr_setrobust_np(pthread_mutexattr_t *attr, int* robustness
);
设置互斥锁强健属性
注:仅当定义了符号 _POSIX_THREAD_PRIO_INHERIT 时,pthread_mutexattr_setrobust_np() 才适用。
attr 指示以前通过调用 pthread_mutexattr_init() 创建的互斥锁属性对象。
robustness 定义在互斥锁的属主失败时的行为。pthread.h 中定义的 robustness 的值为 PTHREAD_MUTEX_ROBUST_NP 或PTHREAD_MUTEX_STALLED_NP。缺省值为 PTHREAD_MUTEX_STALLED_NP。
 
PTHREAD_MUTEX_ROBUST_NP
如果互斥锁的属主失败,则以后对 pthread_mutex_lock() 的所有调用将以不确定的方式被阻塞。
PTHREAD_MUTEX_STALLED_NP
互斥锁的属主失败时,将会解除锁定该互斥锁。互斥锁的下一个属主将获取该互斥锁,并返回错误 EOWNWERDEAD。
int pthread_mutexattr_getrobust_np(const pthread_mutexattr_t *attr, int* robustness
);
获取互斥锁强健属性值




五、条件锁
条件变量的初始化,有静态初始化和动态初始化,静态初始化使用宏
PTHREAD_COND_INITIALIZER;
动态初始化使用pthread_cond_init函数;
1.int pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *attr);
参数说明:参数一:条件变量
 参数二: 条件变量属性,设为NULL则使用默认的条件变量属性 


2.int pthread_cond_destory(pthread_cond_t *cond);  
销毁条件变量,使之还原成初始化状态以前
参数说明:要销毁的条件变量


条件锁的操作
操作有两个:等待和激活。
等待
int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex);  
int pthread_cond_timedwait(pthread_cond_t *cond,pthread_mutex_t *mutex, const timespec *abstime);  
等待条件有两种方式:条件等待pthread_cond_wait()和计时等待
pthread_cond_timedwait(),其中计时等待方式如果在给定时刻前条件没有满足,则返回
ETIMEDOUT,结束等待。
无论哪种等待方式,都必须和一个互斥锁配合。为什么呢?

   解锁和睡眠是原子的:lock --> 检查变量不满足 --> unlock --> sleep;如果变量的改变以及通知事件发生在unlock和sleep中间,那么你不会检测到,也就是错过了这次通知.
   加锁和唤醒是原子的:wakeup -- > lock ----> 检查变量是否满足条件:如果在wakeup之后,在lock之前,其他线程可以修改数据,导致我们Lock后检查的数据可能与我们被唤醒的通知不是一个通知,也就是被1号通知唤醒,却检查了2号通知对变量的改变。


激活
int pthread_cond_signal(pthread_cond_t *cond);  
int pthread_cond_broadcast(pthread_cond_t *cond); 
激发条件有两种形式,pthread_cond_signal()激活一个等待该条件的线程,存在多个等待线程时按入队顺序激活其中一个;而pthread_cond_broadcast()则激活所有等待线程。
当调用pthread_cond_signal或pthread_cond_broadcast激活线程时,pthread_cond_wait()或pthread_cond_timedwait()函数有两个操作,唤醒和加锁(给互斥量加锁),这两个操作是原子的
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值