多线程同步-mutex

来源:互联网 发布:负面情绪 知乎 编辑:程序博客网 时间:2024/04/30 11:14

1. 互斥锁初始化

对互斥锁的初始化有静态初始化和动态初始化两种方式,静态初始化方式:
pthread_mutex_t mutex1 = PTHRAD_MUTEX_INITIALIZER;
动态初始化方式:
pthread_mutex_t mutex1;
pthread_mutex_init(&mutex1,NULL);
或者
pthread_mutext_t mutex1;
pthread_mutexattr_t mta;
pthread_mutexattr_init(&mta);
pthread_mutex_init(&mutex1,&mta);
pthread_mutexattr_destroy(&mta);

1.1 静态初始化

静态初始化的目的是用缺省属性初始化互斥锁,实现方式:

pthread_mutex_t mutex1 = PTHRAD_MUTEX_INITIALIZER;

在IBM技术文档中,提到:
The PTHREAD_MUTEX_INITIALIZER macro initializes the static mutex mutex, setting its attributes to default values. This macro should only be used for static mutexes, as no error checking is performed.
这里的静态并不是指带有static 的mutex,例如:
static pthread_mutex_t mutex1 = PTHREAD_MUTEX_INITIALIZER;
和pthead_mutex_t mutex1 = PTHREAD_MUTEX_INITIALIZER;<必须是全局变量>
都是合法的,所谓的static mutex指的是static allocated.
全局变量和static 变量在内存中存储的地方都是静态区。
在POSIX Threads Programming中提到:

In cases where default mutex  attributes  are  appropriate,  the  macro PTHREAD_MUTEX_INITIALIZER  can  be  used to initialize mutexes that arestatically allocated. The effect shall be equivalent  to  dynamic  initialization by a call to pthread_mutex_init() with parameter attr specified as NULL, except that no error checks are performed.https://computing.llnl.gov/tutorials/pthreads/#Mutexes

这里提到的就是statically allocated.

1.2 动态初始化

/*函数*/
int pthread_mutex_init(pthread_mutex_t *restrict mutex,const pthread_mutexattr_t *restrict attr);

pthread_mutex_init 用指定的属性(attr)来初始化mutex.如果atrr为NULL,初始化的效果和PTHREAD_MUTEX_INITIALIZER是一致的。

如果初始化成功,返回0;其他任何返回值都表示错误。
返回EBUSY:表示再次初始化已经初始化但是还没有销毁的mutex。也就是说pthread_mutex_init,pthread_mutex_destroy成对出现,一旦mutex已经初始化,如果想再次对它进行初始化,必须先执行一次pthead_mutex_destroy,否则就会出现pthead_mutex_init 失败,返回EBUSY。
返回EINVAL:attr属性指无效。
2. 销毁互斥锁

/*函数*/
int pthread_mutex_destroy(pthread_mutex_t *mutex);


调用pthead_mutex_destroy来销毁未锁住的mutex,成功执行之后,mutex变成了未初始化。可以再次对mutex通过pthead_mutex_init或者PTHREAD_MUTEX_INITIALIZER初始化。
返回值:
EBUSY:如果你销毁一个当前被锁住的mutex(例如调用:pthread_cond_wait 或者pthread_cond_timewait),pthread_mutex_destroy返回EBUSY。
EINVAL:如果mutex无效,调用phread_mutex_destroy返回EINVAL。

3. 阻塞锁定互斥锁

/*函数*/
int    pthread_mutex_lock(pthread_mutex_t *mutex);

       我们在这里称调用pthread_mutex_lock的线程为master,当mutex未锁定时,master调用pthread_mutex_lock并成功,此时,master就拥有了mutex。如果此时,mutex已经被别的线程锁定,master就会阻塞在这里,知道mutex空闲。
       如果mutex的类型是PTHREAD_MUTEX_NORMAL,该函数不提供deadlock检查,因此,尝试锁定一个已经locked的mutex,会导致deadlock。如果某个线程尝试解除锁定的互斥锁不是由该线程锁定或未锁定,则将产生不确定的行为。
       如果mutex的类型是PTHREAD_MUTEX_ERRORCHECK,该函数会提供deadlock检查,因此,尝试锁定一个locked的mutex,会返回错误。如果某个线程尝试解除锁定的互斥锁不是由该线程锁定或者未锁定,则将返回错误。
       如果互斥锁类型为 PTHREAD_MUTEX_RECURSIVE,则该互斥锁会保留锁定计数这一概念。线程首次成功获取互斥锁时,锁定计数会设置为 1。线程每重新锁定该互斥锁一次,锁定计数就增加 1。线程每解除锁定该互斥锁一次,锁定计数就减小 1。 锁定计数达到 0 时,该互斥锁即可供其他线程获取。如果某个线程尝试解除锁定的互斥锁不是由该线程锁定或者未锁定,则将返回错误。

如果互斥锁类型是 PTHREAD_MUTEX_DEFAULT,则尝试以递归方式锁定该互斥锁将产生不确定的行为。对于不是由调用线程锁定的互斥锁,如果尝试解除对它的锁定,则会产生不确定的行为。如果尝试解除锁定尚未锁定的互斥锁,则会产生不确定的行为。

成功执行pthread_mutex_lock返回0,返回其它任何值都表示执行失败。

4. 非阻塞锁定互斥锁

/*函数*/
int    pthread_mutex_trylock(pthread_mutex_t *mutex); 


 pthread_mutex_trylock() 是 pthread_mutex_lock() 的非阻塞版本。如果 mutex 所引用的互斥对象当前被任何线程(包括当前线程)锁定,则将立即返回。否则,该互斥锁将处于锁定状态,调用线程拥有该mutex。
成功执行pthread_mutex_trylock,(调用线程拥有mutex)返回0。
返回EBUSY表示该mutex已经被锁定。

5. 解锁互斥锁

/*函数*/
int    pthread_mutex_unlock(pthread_mutex_t *mutex);

pthread_mutex_unlock() 释放互斥锁,成功执行此函数后,该线程不再拥有该互斥锁。互斥锁的释放方式取决于互斥锁的属性。 如果调用 pthread_mutex_unlock() 时有多个线程被 mutex 对象阻塞,则互斥锁变为可用时调度策略可确定获取该互斥锁的线程。 对于 PTHREAD_MUTEX_RECURSIVE 类型的互斥锁,当计数达到零并且调用线程不再对该互斥锁进行任何锁定时,该互斥锁将变为可用。

pthread_mutex_unlock() 在成功完成之后会返回零。其他任何返回值都表示出现了错误。如果出现以下情况,该函数将失败并返回对应的值。

返回EPERM表示当前线程不拥有互斥锁。


原创粉丝点击