UNIX环境高级编程——互斥量属性
互斥量具有一些属性,通过修改这些属性可以控制锁的一些行为。缺省的互斥锁属性及其值如下:
- pshared: PTHREAD_PROCESS_PRIVATE
- type: PTHREAD_MUTEX_DEFAULT
- protocol: PTHREAD_PRIO_NONE
- prioceiling: –
- robustness: PTHREAD_MUTEX_STALLED_NP
pthread_mutexattr_t attr;
int pthread_mutexattr_init(pthread_mutexattr_t *attr);
int pthread_mutexattr_destroy(pthread_mutexattr_t *attr);
int pthread_mutexattr_getpshared(pthread_mutexattr_t *attr,int *pshared);
int pthread_mutexattr_setpshared(pthread_mutexattr_t *attr,int pshared);
参数:pshared的取值可以是: PTHREAD_PROCESS_SHARED,PTHREAD_PROCESS_PRIVATE
说明:如果互斥锁属性对象的pshared属性被置PTHREAD_PROCESS_SHARED。那么由这个属性对象创建的互斥锁将被保存在共享内存中,可以被多个进程中的线程共享。如pshared属性被置为PTHREAD_PROCESS_PRIVATE,那么只有和创建这个互斥锁的线程在同一个进程中的线程才能访问这个互斥锁。
2.获得/修改类型互斥量属性
int pthread_mutexattr_settype(pthread_mutexattr_t *attr,int kind);
int pthread_mutexattr_gettype(pthread_mutexattr_t *attr,int *kind);
- PTHREAD_MUTEX_DEFAULT(缺省的互斥锁类型属性):这种类型的互斥锁不会自动检测死锁。如果一个线程试图对一个互斥锁重复锁定,将会引起不可预料的结果。如果试图解锁一个由别的线程锁定的互斥锁会引发不可预料的结果。如果一个线程试图解锁已经被解锁的互斥锁也会引发不可预料的结果。POSIX标准规定,对于某一具体的实现,可以把这种类型的互斥锁定义为其他类型的互斥锁。
- PTHREAD_MUTEX_NORMAL:这种类型的互斥锁不会自动检测死锁。如果一个线程试图对一个互斥锁重复锁定,将会引起这个线程的死锁。如果试图解锁一个由别的线程锁定的互斥锁会引发不可预料的结果。如果一个线程试图解锁已经被解锁的互斥锁也会引发不可预料的结果。
- PTHREAD_MUTEX_ERRORCHECK:这种类型的互斥锁会自动检测死锁。 如果一个线程试图对一个互斥锁重复锁定,将会返回一个错误代码。 如果试图解锁一个由别的线程锁定的互斥锁将会返回一个错误代码。如果一个线程试图解锁已经被解锁的互斥锁也将会返回一个错误代码。
- PTHREAD_MUTEX_RECURSIVE:如果一个线程对这种类型的互斥锁重复上锁,不会引起死锁。一个线程对这类互斥锁的多次重复上锁必须由这个线程来重复相同数量的解锁,这样才能解开这个互斥锁,别的线程才能得到这个互斥锁。如果试图解锁一个由别的线程锁定的互斥锁将会返回一个错误代码。如果一个线程试图解锁已经被解锁的互斥锁也将会返回一个错误代码。这种类型的互斥锁只能是进程私有的(作用域属性为PTHREAD_PROCESS_PRIVATE)。
3.设置/获取互斥锁的协议属性
int pthread_mutexattr_setprotocol(pthread_mutexattr_t *attr, int protocol);
int pthread_mutexattr_getprotocol(const pthread_mutexattr_t *attr, int *protocol);
互斥锁协议属性的可能值及其含义:
- PTHREAD_PRIO_NONE:线程的优先级和调度不会受到互斥锁拥有权的影响。
- PTHREAD_PRIO_INHERIT:当高优先级的等待低优先级的线程锁定互斥量时,低优先级的线程以高优先级线程的优先级运行。这种方式将以继承的形式传递。当线程解锁互斥量时,线程的优先级自动被将到它原来的优先级。(“优先级继承”意味着,当一个线程在由另一个低优先级线程拥有的互斥量上等待时,后者的优先级将被增加到等待线程的优先级.)
- PTHREAD_PRIO_PROTECT:拥有该类型的互斥量的线程将以自己的优先级和它拥有的互斥量的线程将以自己的优先级和它拥有的互斥量的优先级较高者运行,其他等待该线程拥有的锁得线程对该线程的调度优先级没有影响。
注意:PTHREAD_PRIO_INHERIT 和 PTHREAD_PRIO_PROTECT 只有在采用实时调度策略SCHED_FIFO 或SCHED_RR的优先级进程内可用。
一个线程可以同时拥有多个混合使用PTHREAD_PRIO_INHERIT 和PTHREAD_PRIO_PROTECT协议属性初始化的互斥锁。在这种情况下,该线程将以通过其中任一协议获取的最高优先级执行。pthread_mutexattr_getprotocol可用来获取互斥锁属性对象的协议属性。
4.设置/获取互斥锁属性对象的优先级上限属性
int pthread_mutexattr_setprioceiling(pthread_mutexatt_t *attr, int prioceiling, int *oldceiling);
int pthread_mutexattr_getprioceiling(const pthread_mutexatt_t *attr, int *prioceiling);
prioceiling指定已初始化互斥锁的优先级上限。优先级上限定义执行互斥锁保护的临界段时的最低优先级。prioceiling 位于SCHED_FIFO 所定义的优先级的最大范围内。要避免优先级倒置,请将prioceiling 设置为高于或等于可能会锁定特定互斥锁的所有线程的最高优先级。oldceiling 用于返回以前的优先级上限值。
pthread_mutex_setprioceiling可更改互斥锁mutex的优先级上限prioceiling。
pthread_mutex_setprioceiling可锁定互斥锁(如果未锁定的话),或者一直处于阻塞状态,直到它成功锁定该互斥锁,更改该互斥锁的优先级上限并将该互斥锁释放为止。锁定互斥锁的过程无需遵循优先级保护协议。
如果 pthread_mutex_setprioceiling成功,则将在 old_ceiling 中返回以前的优先级上限值。如果pthread_mutex_setprioceiling失败,则互斥锁的优先级上限保持不变。pthread_mutex_getprioceiling会返回mutex 的优先级上限prioceiling。
注意:“优先级上限”协议意味着当一个线程拥有互斥量时,它将以指定的优先级运行。
5.设置/获取互斥锁的强健属性
int pthread_mutexattr_setrobust_np(pthread_mutexattr_t *attr, int *robustness);
int pthread_mutexattr_getrobust_np(const pthread_mutexattr_t *attr, int *robustness);
robustness 定义在互斥锁的持有者“死亡”时的行为。pthread.h 中定义的robustness 的值为PTHREAD_MUTEX_ROBUST_NP 或 PTHREAD_MUTEX_STALLED_NP。缺省值为PTHREAD_MUTEX_STALLED_NP。
- PTHREAD_MUTEX_STALLED_NP: 如果互斥锁的持有者死亡,则以后对pthread_mutex_lock() 的所有调用将以不确定的方式被阻塞。
- PTHREAD_MUTEX_ROBUST_NP: 如果互斥锁的持有者“死亡”了,或者持有这样的互斥锁的进程unmap了互斥锁所在的共享内存或者持有这样的互斥锁的进程执行了exec调用,则会解除锁定该互斥锁。互斥锁的下一个持有者将获取该互斥锁,并返回错误EOWNWERDEAD。
如果互斥锁具有PTHREAD_MUTEX_ROBUST_NP的属性,则应用程序在获取该锁时必须检查pthread_mutex_lock 的返回代码看获取锁时是否返回了EOWNWERDEAD错误。如果是,则
- 互斥锁的新的持有者应使该互斥锁所保护的状态保持一致。因为互斥锁的上一个持有者“死亡”时互斥锁所保护的状态可能出于不一致的状态。
- 如果互斥锁的新的持有者能够使该状态保持一致,请针对该互斥锁调用pthread_mutex_consistent_np(),并解除锁定该互斥锁。
- 如果互斥锁的新的持有者无法使该状态保持一致,请勿针对该互斥锁调用pthread_mutex_consistent_np(),而是解除锁定该互斥锁。所有等待的线程都将被唤醒,以后对pthread_mutex_lock() 的所有调用都将无法获取该互斥锁。返回错误为ENOTRECOVERABLE。
如果一个线程获取了互斥锁,但是获取时得到了EOWNERDEAD的错误,然后它终止并且没有释放互斥锁 ,则下一个持有者获取该锁时将返回代码EOWNERDEAD。
注意:
1、互斥量需要时间来加锁和解锁。锁住较少互斥量的程序通常运行得更快。所以,互斥量应该尽量少,够用即可,每个互斥量保护的区域应则尽量大。
2、互斥量的本质是串行执行。如果很多线程需要频繁地加锁同一个互斥量,则线程的大部分时间就会在等待,这对性能是有害的。如果互斥量保护的数据(或代码)包含彼此无关的片段,则可以特大的互斥量分解为几个小的互斥量来提高性能。这样,任意时刻需要小互斥量的线程减少,线程等待时间就会减少。所以,互斥量应该足够多(到有意义的地步),每个互斥量保护的区域则应尽量的少。
3、POSIX线程锁机制的Linux实现都不是取消点,因此,延迟取消类型的线程不会因收到取消信号而离开加锁等待。
4、线程在加锁后解锁前被取消,锁将永远保持锁定状态。因此如果在关键区段内有取消点存在,或者设置了异步取消类型,则必须在退出回调函数中解锁。
5、锁机制不是异步信号安全的,也就是说,不应该在信号处理过程中使用互斥锁,否则容易造成死锁。
本文来源于以前写的博客:《posix多线程有感--线程高级编程(互斥量属性)》,并做部分修改。
UNIX环境高级编程——互斥量属性的更多相关文章
- UNIX环境高级编程——线程属性
pthread_attr_t 的缺省属性值 属性 值 结果 scope PTHREAD_SCOPE_PROCESS 新线程与进程中的其他线程发生竞争. detachstate PTHREAD_CREA ...
- (九) 一起学 Unix 环境高级编程 (APUE) 之 线程
. . . . . 目录 (一) 一起学 Unix 环境高级编程 (APUE) 之 标准IO (二) 一起学 Unix 环境高级编程 (APUE) 之 文件 IO (三) 一起学 Unix 环境高级编 ...
- (十) 一起学 Unix 环境高级编程 (APUE) 之 线程控制
. . . . . 目录 (一) 一起学 Unix 环境高级编程 (APUE) 之 标准IO (二) 一起学 Unix 环境高级编程 (APUE) 之 文件 IO (三) 一起学 Unix 环境高级编 ...
- (十二) 一起学 Unix 环境高级编程 (APUE) 之 进程间通信(IPC)
. . . . . 目录 (一) 一起学 Unix 环境高级编程 (APUE) 之 标准IO (二) 一起学 Unix 环境高级编程 (APUE) 之 文件 IO (三) 一起学 Unix 环境高级编 ...
- 《UNIX环境高级编程(第3版)》
<UNIX环境高级编程(第3版)> 基本信息 原书名:Advanced Programming in the UNIX Environment (3rd Edition) (Addison ...
- UNIX环境高级编程——管道读写规则和pipe Capacity、PIPE_BUF
一.当没有数据可读时O_NONBLOCK disable:read调用阻塞,即进程暂停执行,一直等到有数据来到为止. O_NONBLOCK enable:read调用返回-1,errno值为EAGAI ...
- 【UNIX环境高级编程】线程同步
当多个线程共享相同的内存时,需要确保每个线程看到一致的数据视图.如果每个线程使用的变量都是其他线程不会读取和修改的,那么就不存在一致性问题.同样,如果变量是只读的也不会有一致性问题.但是,当一个线程可 ...
- UNIX环境高级编程——TCP/IP网络编程 常用网络信息检索函数
UNIX环境高级编程——TCP/IP网络编程 常用网络信息检索函数 gethostname() getppername() getsockname() gethostbyname() ...
- unix环境高级编程基础知识之第二篇(3)
看了unix环境高级编程第三章,把代码也都自己敲了一遍,另主要讲解了一些IO函数,read/write/fseek/fcntl:这里主要是c函数,比较容易,看多了就熟悉了.对fcntl函数讲解比较到位 ...
随机推荐
- 学习sharding-jdbc 分库分表扩展框架
先丢代码地址 https://gitee.com/a247292980/sharding-jdbc 再丢pom.xml的dependency <properties> <projec ...
- CentOS6.8虚拟机安装及ORALCE安装记录
CENTOS6.8安装数据库及设置自启动脚本教程 作者:张欣橙 本文所需要的所有参数均位于文末附录中 一.新建虚拟机 选择下一步 选择下一步 选择稍后安装操作系统 选择LINUX 版本 CentOS ...
- JavaScript正则表达式模式匹配(6)——常用的正则表达式
1.检查邮政编码 var pattern=/[1-9][0-9]{5}/; // 必须是6位,必须是数字,第一位不能为0 var str='274200'; alert(pattern.test(st ...
- WUOJ-ACM :1003: 零起点学算法78——牛牛
武汉科技大学ACM :1003: 零起点学算法78--牛牛Problem Description牛牛是一种纸牌游戏,总共5张牌,规则如下: 如果找不到3张牌的点数之和是10的倍数,则为没牛: 如果其中 ...
- 聊聊jstack的工作原理
实现一个jstack 在聊Jstack得工作原理前呢,不如让我们先写一个简单的jstack玩玩.不用怕,很简单的,就几行代码的事,看: public class MyJstack { public s ...
- miracl去除某些特殊信息
只需要在mirdef.h中增加定义 #define MR_STRIPPED_DOWN 即可在编译的时候,去掉错误信息 #define MIRACL 32 #define MR_LITTLE_ENDI ...
- 让你的代码减少三倍!使用kotlin开发Android(五) 监听器
本文同步自 博主的私人博客wing的地方酒馆 在前面的博客中,有一个栗子,是点击按钮转跳的监听器. button.setOnClickListener { val user = User(" ...
- 修改hosts立刻生效不必重启
有时我们会通过修改Hosts文件(路径为系统盘:\WINDOWS\system32\drivers\etc\hosts),在修改并保存Hosts文件后需要重启才能使设置生效. 这时可以打开命令提示符 ...
- hibernate5学习之理解数据库级并发
本文作者:苏生米沿 本文地址:http://blog.csdn.net/sushengmiyan/article/details/50551741 当我们谈起隔离的时候,我们总是假定两个物体直接要么隔 ...
- 对 /dev/shm 认识
一./dev/shm理论 /dev/shm/是linux下一个非常有用的目录,因为这个目录不在硬盘上,而是在内存里.因此在linux下,就不需要大费周折去建 ramdisk,直接使用/dev/shm/ ...