pthread锁之pthread_mutexattr_t

Posted tianzeng

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了pthread锁之pthread_mutexattr_t相关的知识,希望对你有一定的参考价值。

相关函数说明

初始化互斥锁属性对象       pthread_mutexattr_init 语法
销毁互斥锁属性对象        pthread_mutexattr_destroy 语法 设置互斥锁范围          pthread_mutexattr_setpshared 语法 获取互斥锁范围          pthread_mutexattr_getpshared 语法 设置互斥锁的类型属性       pthread_mutexattr_settype 语法 获取互斥锁的类型属性       pthread_mutexattr_gettype 语法 设置互斥锁属性的协议       pthread_mutexattr_setprotocol 语法 获取互斥锁属性的协议       pthread_mutexattr_getprotocol 语法 设置互斥锁属性的优先级上限   pthread_mutexattr_setprioceiling 语法 获取互斥锁属性的优先级上限    pthread_mutexattr_getprioceiling 语法 设置互斥锁的优先级上限      pthread_mutex_setprioceiling 语法 获取互斥锁的优先级上限      pthread_mutex_getprioceiling 语法 设置互斥锁的强健属性       pthread_mutexattr_setrobust_np 语法 获取互斥锁的强健属性       pthread_mutexattr_getrobust_np 语法

 

定义锁

pthread_mutex_t lock; 

定义mutexattr_t变量

pthread_mutexattr_t attr; 

设置mutexattr属性

pthread_mutexattr_init(&attr); // 初始化attr为默认属性  
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_TIMED_NP); // 设置attr属性为PTHREAD_MUTEX_TIMED_NP,即默认属性(当一个线程加锁后,其余请求锁的线程形成等待队列,在解锁后按优先级获得锁)

其他相关属性

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动作相同。 此处特别注意linux和windows下的errno.h中的EDEADLK对应的宏的值有差别:linux下为35,windows下36   
} type; 

linux下pthread.h中的线程属性

/* Mutex types.  */  
enum  
{  
  PTHREAD_MUTEX_TIMED_NP,  
  PTHREAD_MUTEX_RECURSIVE_NP,  
  PTHREAD_MUTEX_ERRORCHECK_NP,  
  PTHREAD_MUTEX_ADAPTIVE_NP  
#ifdef __USE_UNIX98  
  ,  
  PTHREAD_MUTEX_NORMAL = PTHREAD_MUTEX_TIMED_NP,  
  PTHREAD_MUTEX_RECURSIVE = PTHREAD_MUTEX_RECURSIVE_NP,  
  PTHREAD_MUTEX_ERRORCHECK = PTHREAD_MUTEX_ERRORCHECK_NP,  
  PTHREAD_MUTEX_DEFAULT = PTHREAD_MUTEX_NORMAL  
#endif  
#ifdef __USE_GNU  
  /* For compatibility.  */  
  , PTHREAD_MUTEX_FAST_NP = PTHREAD_MUTEX_TIMED_NP  
#endif  
};  
  • 互斥锁属性

       互斥锁的属性在创建锁的时候指定,在LinuxThreads实现中仅有一个锁类型属性,不同的锁类型在试图对一个已经被锁定的互斥锁加锁时表现不同。当前(glibc2.2.3,linuxthreads0.9)有四个值可供选择:

       * PTHREAD_MUTEX_TIMED_NP,这是缺省值,也就是普通锁。当一个线程加锁以后,其余请求锁的线程将形成一个等待队列,并在解锁后按优先级获得锁。这种锁策略保证了资源分配的公平性。

       * PTHREAD_MUTEX_RECURSIVE_NP,嵌套锁,允许同一个线程对同一个锁成功获得多次,并通过多次unlock解锁。如果是不同线程请求,则在加锁线程解锁时重新竞争。

       * PTHREAD_MUTEX_ERRORCHECK_NP,检错锁,如果同一个线程请求同一个锁,则返回EDEADLK,否则与PTHREAD_MUTEX_TIMED_NP类型动作相同。这样就保证当不允许多次加锁时不会出现最简单情况下的死锁。

       * PTHREAD_MUTEX_ADAPTIVE_NP,适应锁,动作最简单的锁类型,仅等待解锁后重新竞争。

 

  • lock相关函数描述

函数名

pthread_mutex_lock; pthread_mutex_trylock,;pthread_mutex_unlock - lock and unlock a mutex

概要

#include <pthread.h>  
  
int pthread_mutex_lock(pthread_mutex_t *mutex);  
int pthread_mutex_trylock(pthread_mutex_t *mutex);  
int pthread_mutex_unlock(pthread_mutex_t *mutex);  

 

描述

pthread_mutex_lock()函数锁住由mutex指定的mutex对象。如果mutex已经被锁住,调用这个函数的线程阻塞直到mutex可用为止。这跟函数返回的时候参数mutex指定的mutex对象变成锁住状态,同时该函数的调用线程成为该mutex对象的拥有者。

1.PTHREAD_MUTEX_NORMAL,不进行deadlock detection(死锁检测)。企图进行relock这个mutex会导致deadlock.如果一个线程对未加锁的或已经unlock的mutex对象进行unlock操作,结果是不未知的。

2.PTHREAD_MUTEX_ERRORCHECK,那么将进行错误检查。如果一个线程企图对一个已经锁住的mutex进行relock,将返回一个错误。如果一个线程对未加锁的或已经unlock的mutex对象进行unlock操作,将返回一个错误。

3.PTHREAD_MUTEX_RECURSIVE,mutex会有一个锁住次数(lock count)的概念。当一个线程成功地第一次锁住一个mutex的时候,锁住次数(lock count)被设置为1,每一次一个线程unlock这个mutex的时候,锁住次数(lock count)就减1。当锁住次数(lock count)减少为0的时候,其他线程就能获得该mutex锁了。如果一个线程对未加锁的或已经unlock的mutex对象进行unlock操作,将返回一个错误,如果一个线程对这种类型的互斥锁重复上锁,不会引起死锁,一个线程对这类互斥锁的多次重复上锁必须由这个线程来重复相同数量的解锁,这样才能解开这个互斥锁,别的线程才能得到这个互斥锁。如果试图解锁一个由别的线程锁定的互斥锁将会返回一个错误代码。如果一个线程试图解锁已经被解锁的互斥锁也将会返回一个错误代码。这种类型的互斥锁只能是进程私有的(作用域属性为PTHREAD_PROCESS_PRIVATE)

4.PTHREAD_MUTEX_DEFAULT,企图递归的获取这个mutex的锁的结果是不确定的。unlock一个不是被调用线程锁住的mutex的结果也是不确定的。企图unlock一个未被锁住的mutex导致不确定的结果。

pthread_mutex_trylock()调用在参数mutex指定的mutex对象当前被锁住的时候立即返回,除此之外,pthread_mutex_trylock()跟pthread_mutex_lock()功能完全一样。
The pthread_mutex_unlock()函数释放有参数mutex指定的mutex对象的锁。如果被释放取决于该Mutex对象的类型属性。如果有多个线程为了获得该mutex锁阻塞,调用pthread_mutex_unlock()将是该mutex可用,一定的调度策略将被用来决定哪个线程可以获得该mutex锁。(在mutex类型为PTHREAD_MUTEX_RECURSIVE的情况下,只有当lock count 减为0并且调用线程在该mutex上已经没有锁的时候)(翻译到这里,才觉得我的这个锁概念是多么模糊)
如果一个线程在等待一个mutex锁得时候收到了一个signal,那么在从signal handler返回的时候,该线程继续等待该mutex锁,就像这个线程没有被中断一样。
返回值
成功,pthread_mutex_lock()和pthread_mutex_unlock() 返回0,否则返回一个错误的提示码
pthread_mutex_trylock() 在成功获得了一个mutex的锁后返回0,否则返回一个错误提示码

错误

pthread_mutex_lock() 和 pthread_mutex_unlock()失败的时候
[EINVAL]
mutex在生成的时候,它的protocol属性的值是PTHREAD_PRIO_PROTECT,同时调用线程的优先级(priority)比该mutex的当前prority上限高
pthread_mutex_trylock() 函数在一下情况会失败:
[EBUSY]
The mutex could not be acquired because it was already locked.
mutex已经被锁住的时候无法再获取锁
The pthread_mutex_lock()pthread_mutex_trylock() andpthread_mutex_unlock() functions may fail if:
[EINVAL]
mutex指向的mutex未被初始化
[EAGAIN]
Mutex的lock count(锁数量)已经超过 递归索的最大值,无法再获得该mutex锁
pthread_mutex_lock() 函数在一下情况下会失败:
[EDEADLK]
当前线程已经获得该mutex锁
pthread_mutex_unlock() 函数在以下情况下会失败:
[EPERM]
当前线程不是该mutex锁的拥有者
所有的这些函数的错误返回值都不会是[EINTR]
 

应用互斥量需要注意的几点

1、互斥量需要时间来加锁和解锁。锁住较少互斥量的程序通常运行得更快。所以,互斥量应该尽量少,够用即可,每个互斥量保护的区域应则尽量大。

2、互斥量的本质是串行执行。如果很多线程需要领繁地加锁同一个互斥量,

则线程的大部分时间就会在等待,这对性能是有害的。如果互斥量保护的数据(或代码)包含彼此无关的片段,则可以特大的互斥量分解为几个小的互斥量来提高性能。这样,任意时刻需要小互斥量的线程减少,线程等待时间就会减少。所以,互斥量应该足够多(到有意义的地步),每个互斥量保护的区域则应尽量的少。

https://blog.csdn.net/msdnwolaile/article/details/52140622

以上是关于pthread锁之pthread_mutexattr_t的主要内容,如果未能解决你的问题,请参考以下文章

锁之synchronized

001Java锁之synchronized

C# 多线程锁之ReaderWriterLockSlim

并发编程经历 同步加锁之业务锁

SQL-乐观锁,悲观锁之于并发

Java多线程Day23-JUC锁之共享锁