线程优先级posix多线程有感--线程高级编程(互斥量属性)
本文纯属个人见解,是对前面学习的总结,如有描述不正确的地方还请高手指正~
互斥量有具一些属性,通过修改这些属性可以制控锁的一些行为。省缺的互斥锁属性及其值如下:
- pshared: PTHREAD_PROCESS_PRIVATE
- type: PTHREAD_MUTEX_DEFAULT
- protocol: PTHREAD_PRIO_NONE
- prioceiling: –
- robustness: PTHREAD_MUTEX_STALLED_NP
1.取得/修改享共互斥量属性
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、锁制机不是步异信号全安的,也就是说,不该应在信号处理程过当中用使互斥锁,否则易容成造锁死。
文章结束给大家分享下程序员的一些笑话语录:
Borland说我很有前途,Sun笑了;Sun说我很有钱,IBM笑了;IBM说我很专业,Sybase笑了;Sybase说我数据库很牛,Oracle笑了;Oracle说我是开放的,Linux笑了;Linux说我要打败Unix,微软笑了;微软说我的系统很稳定,我们都笑了。