您的位置:首页 > 其它

Mutext,pthread_mutext_t

2016-01-10 12:53 375 查看

pthread_mutext_t的用法

基本函数

#include <pthread.h>
// 基本操作
int pthread_mutex_destroy(pthread_mutex_t *mutex);
int pthread_mutex_init(pthread_mutex_t *restrict mutex,
const pthread_mutexattr_t *restrict attr);
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
int pthread_mutex_lock(pthread_mutex_t *mutex);
int pthread_mutex_trylock(pthread_mutex_t *mutex);
int pthread_mutex_unlock(pthread_mutex_t *mutex);


注意

1. pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;这种静态初始化形式是合法的,相当于pthread_mutext_init(&obj, NULL)

2. 重复初始化是错误的,行为未定义

3. 还处于lock状态是不能destroy的,行为未定义

4. destory以后继续使用的行为是未定义的;不过可以再次初始化,然后使用

5. 如果block等待锁期间,收到了信号,那么在执行完信号处理函数以后,会继续block,就像什么也没发生

6. 对一个没初始化的锁执行加锁或解锁,或返回EINVAL

7. pthread_mutex_trylock是非阻塞版本,如果调用pthread_mutext_lock会成功,那么它也会成功,如果调用pthread_mutext_lock会block,那么它会返回EBUSY。

属性设置

// 属性
int pthread_mutexattr_destroy(pthread_mutexattr_t *attr);
int pthread_mutexattr_init(pthread_mutexattr_t *attr);


pthread_mutexattr_destroy以后继续使用对象,行为未定义。但可以再次初始化后使用。

pthread_mutexattr_init重复调用,反复初始化,行为未定义。

pthread_mutextattr_t对象用来初始化mutex是拷贝的,一个可以初始化多个。后续修改attr对象不影响已经初始化了的mutex

递归锁

int pthread_mutexattr_gettype(const pthread_mutexattr_t *restrict attr,
int *restrict type);
int pthread_mutexattr_settype(pthread_mutexattr_t *attr, int type);


对于递归的支持,依赖于锁的类型。默认值是PTHREAD_MUTEX_DEFAULT

* PTHREAD_MUTEX_NORMAL:不支持递归,同一个线程在第二次lock的时候,陷入死锁

* PTHREAD_MUTEX_ERRORCHECK:不支持递归,但同一个线程第二次lock的时候,会返回一个错误EDEADLK

* PTHREAD_MUTEX_RECURSIVE:支持递归,维护一个“锁住次数”的变量。.递归加锁次数超系统最大值,返回EAGAIN。不要跟条件变量一起用:It is advised that an application should not use a PTHREAD_MUTEX_RECURSIVE mutex with condition variables because the implicit unlock performed for a pthread_cond_timedwait() or pthread_cond_wait()

may not actually release the mutex (if it had been locked multiple times). If this happens, no other thread can satisfy the condition of the predicate.

* PTHREAD_MUTEX_DEFAULT:不支持递归。同一个线程在第二次lock的时候,行为是未定义的

优先级协议设置

// 优先级相关协议
int pthread_mutexattr_getprotocol(const pthread_mutexattr_t *
restrict attr, int *restrict protocol);
int pthread_mutexattr_setprotocol(pthread_mutexattr_t *attr,
int protocol);

// 手工设置ceil值
int pthread_mutex_getprioceiling(const pthread_mutex_t *restrict mutex,
int *restrict prioceiling);
int pthread_mutex_setprioceiling(pthread_mutex_t *restrict mutex,
int prioceiling, int *restrict old_ceiling);


PTHREAD_PRIO_NONE

PTHREAD_PRIO_INHERIT

PTHREAD_PRIO_PROTECT。那么线程的优先级应该<=mutex的ceil值。因为ceil值是根据所有用到这个mutex的线程算出来的。如果发现线程的优先级>mutex的ceil,则在lock或者trylock的时候返回EINVAL错误。

程序退出导致死锁

int pthread_mutexattr_setrobust(pthread_mutexattr_t *attr, int robust);
int pthread_mutexattr_getrobust(pthread_mutexattr_t *attr, int *robust);


PTHREAD_MUTEX_STALLED - 解决不了,退出以后其他任务继续block,死锁了。

PTHREAD_MUTEX_ROBUST - 可以解决,退出以后,mutex被解锁,下一个任务会得到锁,然后返回一个错误码为EOWNERDEAD。这时候你需要调用 pthread_mutex_consistent 函数来清除这种状态。然后处理,正常地unlock,后面就跟一般的mutex一样了。如果没有用mutex_consistent,直接unlock,则这个mutex就会永远处于错误状态,任何试图lock的请求都会返回ENOTRECOVERABLE错误。这个情况下就只有destory一条路了。

多进程

// 是否支持多进程访问
int pthread_mutexattr_getpshared(const pthread_mutexattr_t *
restrict attr, int *restrict pshared);
int pthread_mutexattr_setpshared(pthread_mutexattr_t *attr,
int pshared);


取值可以为:

* PTHREAD_PROCESS_SHARED.支持多进程

* PTHREAD_PROCESS_PRIVATE:默认值。多进程试图lock的行为是未定义的。

*

超时

#include <pthread.h>
#include <time.h>
int pthread_mutex_timedlock(pthread_mutex_t *restrict mutex,
const struct timespec *restrict abs_timeout);


超时后返回ETIMEDOUT错误。

所有的函数返回EINTR都是不可能的,肯定是出错了。

处理意外释放

PTHREAD_MUTEX_NORMAL和PTHREAD_MUTEX_DEFAULT:解锁一个别的线程lock住的锁,或者根本没有lock的锁,行为未定义

PTHREAD_MUTEX_ERRORCHECK和PTHREAD_MUTEX_RECURSIVE:解锁一个别的线程lock住的锁,或者根本没有lock的锁,返回EPERM

总结

总结一下,要做到dead-lock free,就要做到对递归安全、对退出安全。

pthread_mutexattr_t attr;
pthread_mutex_t mutex;
// 类型看情况选择PTHREAD_MUTEX_RECURSIVE或PTHREAD_MUTEX_ERRORCHECK
// 选择PTHREAD_MUTEX_ROBUST;如果编译器不支持,那就在lock的时候用timeout吧
lock的时候要处理的错误:
EPERM和EOWNERDEAD
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: