互斥锁的属性

简介: 互斥锁的属性

在笔记互斥锁的死锁中,初始化互斥锁 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 可以设置为两种情况:

  1. PTHREAD_PROCESS_PRIVATE,表示互斥锁只能在一个进程内部的两个线程进行互斥(默认情况
  2. 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 用来定义互斥锁的类型,其类型可以被设置为如下几种情况。

  1. PTHREAD_MUTEX_NORMAL标准互斥锁,该类型的互斥锁不具备死锁检测功能。
  2. PTHREAD_MUTEX_ERRORCHECK检错互斥锁,对此互斥锁的所有操作都会执行错误检测,这种互斥锁运行起来较一般类型慢,不过却可以作为调试,以发现后续程序在哪里违反了互斥锁的使用规则。
  3. 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
目录
相关文章
|
4月前
|
Java
锁对象
锁对象
130 73
|
3月前
|
缓存 数据库
读写锁和互斥锁的区别
【10月更文挑战第6天】
86 1
|
8月前
|
测试技术 Go
互斥锁与读写互斥锁的妙用
互斥锁与读写互斥锁的妙用
76 0
|
8月前
|
SQL 数据库 索引
锁的类型-
锁的类型-
90 0
方法锁、对象锁、类锁的意义和区别
方法锁、对象锁、类锁的意义和区别
|
设计模式 安全 算法
Java多线程(二)、线程的生命周期、线程的同步、Synchronized的使用方法、同步代码块、同步方法、同步机制中的锁、同步的范围、Lock(锁、不会释放锁的操作、单例设计模式之懒汉式(线程安全)
Java多线程(二)、线程的生命周期、线程的同步、Synchronized的使用方法、同步代码块、同步方法、同步机制中的锁、同步的范围、Lock(锁、不会释放锁的操作、单例设计模式之懒汉式(线程安全)
Java多线程(二)、线程的生命周期、线程的同步、Synchronized的使用方法、同步代码块、同步方法、同步机制中的锁、同步的范围、Lock(锁、不会释放锁的操作、单例设计模式之懒汉式(线程安全)
|
Java 程序员 API
java多线程——显式锁 vs 隐式锁
java多线程——显式锁 vs 隐式锁
java多线程——显式锁 vs 隐式锁