在笔记互斥锁的死锁中,初始化互斥锁 pthread_mutex_init()
函数中参数 attr
为指定互斥锁的属性,而一般默认传参为 NULL
,表示执行该互斥锁的默认属性。本笔记单独讨论互斥锁的属性。
#include <pthread.h> int pthread_mutexattr_destroy(pthread_mutexattr_t *attr); int pthread_mutexattr_init(pthread_mutexattr_t *attr);点击复制复制失败已复制
pthread_mutexattr_init()
函数为初始化互斥锁属性,一般采用默认的方式传参。 pthread_mutexattr_destroy()
函数摧毁互斥锁属性。
#include <pthread.h> int pthread_mutexattr_getpshared(const pthread_mutexattr_t *restrict attr, int *restrict pshared); int pthread_mutexattr_setpshared(pthread_mutexattr_t *attr, int pshared);点击复制复制失败已复制
pthread_mutexattr_getpshared()
函数和 pthread_mutexattr_setpshared()
函数的功能分别为获得互斥锁的属性、设置互斥锁的属性。参数 attr
表示互斥锁的属性。参数 pshared
可以设置为两种情况:
PTHREAD_PROCESS_PRIVATE
,表示互斥锁只能在一个进程内部的两个线程进行互斥(默认情况)PTHREAD_PROCESS_SHARED,
互斥锁可用于两个不同进程中的线程进行互斥,使用时需要在共享内存中分配互斥锁,再为互斥锁指定该属性即可。
pthread_mutexattr_gettype()
函数和 pthread_mutexattr_settype()
函数用来获得以及设置互斥锁的类型。
#include <pthread.h> int pthread_mutexattr_gettype(const pthread_mutexattr_t *restrict attr, int *restrict type); int pthread_mutexattr_settype(pthread_mutexattr_t *attr, int type);点击复制复制失败已复制
参数 type
用来定义互斥锁的类型,其类型可以被设置为如下几种情况。
PTHREAD_MUTEX_NORMAL
:标准互斥锁,该类型的互斥锁不具备死锁检测功能。PTHREAD_MUTEX_ERRORCHECK
:检错互斥锁,对此互斥锁的所有操作都会执行错误检测,这种互斥锁运行起来较一般类型慢,不过却可以作为调试,以发现后续程序在哪里违反了互斥锁的使用规则。PTHREAD_MUTEX_RECURSIVE
:递归互斥锁,该互斥锁维护有一个锁计数器,线程上锁则会将锁计数器的值加1,解锁则会将锁计数器的值减1。只有当锁计数器值降至0
时,才会释放该互斥锁。这一类互斥锁与普通互斥锁的区别在于,同一个线程可以多次获得同一个递归锁,不会产生死锁。而如果一个线程多次获得同一个普通锁,则会产生死锁。Linux
下的互斥锁默认属性为非递归的。
接下来展示函数的基本操作,注意示例只展示锁的属性设置,不创建线程执行任务。对互斥锁的属性进行初始化,之后选择命令传参设置互斥锁的类型,然后初始化互斥锁,对互斥锁进行操作,以此测试互斥锁的类型。
#include <pthread.h> #include <stdio.h> #include <stdlib.h> #include <string.h> int main(int argc, const char *argv[]) { // 定义互斥锁 pthread_mutex_t mutex; if (argc < 2) { printf("input mutex type\n"); return -1; } // 定义互斥锁属性 pthread_mutexattr_t mutexattr; // 设置互斥锁的类型,error:检错互斥锁;normal:标准互斥锁;recursive:递归互斥锁 pthread_mutexattr_init(&mutexattr); if (!strcmp(argv[1], "error")) { pthread_mutexattr_settype(&mutexattr, PTHREAD_MUTEX_ERRORCHECK); printf("set error success\n"); } else if (!strcmp(argv[1], "normal")) { pthread_mutexattr_settype(&mutexattr, PTHREAD_MUTEX_NORMAL); printf("set normal success\n"); } else if (!strcmp(argv[1], "recursive")) { pthread_mutexattr_settype(&mutexattr, PTHREAD_MUTEX_RECURSIVE); printf("set recursive success\n"); } // 初始化互斥锁 pthread_mutex_init(&mutex, &mutexattr); // 初次上锁 if (pthread_mutex_lock(&mutex) != 0) { printf("lock failed\n"); } else { printf("lock success\n"); } // 第二次上锁 if (pthread_mutex_lock(&mutex) != 0) { printf("lock failed\n"); } else { printf("lock success\n"); } // 加锁几次,同样也要释放几次 pthread_mutex_unlock(&mutex); pthread_mutex_unlock(&mutex); // 销毁互斥锁属性和互斥锁 pthread_mutexattr_destroy(&mutexattr); pthread_mutex_destroy(&mutex); return 0; }点击复制复制失败已复制
给程序传入不同的参数,使互斥锁设置不同的类型,效果如下:
- 检错互斥锁
$ gcc main2.c && ./a.out error set error success lock success lock failed点击复制复制失败已复制
- 普通互斥锁
$ gcc main2.c && ./a.out normal set normal success lock success ^C点击复制复制失败已复制
提示
这里程序阻塞了
- 递归互斥锁
$ gcc main2.c && ./a.out recursive set recursive success lock success lock success