31-线程属性——互斥锁类型

1. 创建互斥量的两种方式


  就像线程具有属性一样,用于线程互斥的互斥量的也有相应的属性,互斥量属性的数据类型是用pthread_mutexattr_t结构来表示的,在使用互斥量前必须初始化。

  创建互斥量有两种方法:静态创建和动态创建。对于静态创建而言,POSIX定义了一个宏PTHREAD_MUTEX_INITIALIZER来静态初始化互斥量,使用方法如下:

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

  对于动态创建互斥量则是使用pthread_mutex_init函数初始化互斥量,参数attr用于指定互斥量的属性,互斥量用完对应的要调用pthread_mutex_destroy函数销毁互斥量,具体如何动态创建互斥量,前面已经介绍了,这里就不再赘述了(参考:27-线程同步——互斥量)。


2. 互斥量共享属性相关函数


pthread_mutexattr_t是互斥锁属性的数据类型,表示互斥锁的一些属性相关的信息。

//初始化互斥锁属性
pthread_mutexattr_init(pthread_mutexattr_t attr);

//销毁互斥锁属性
pthread_mutexattr_destroy(pthread_mutexattr_t attr);

//用于获取互斥锁属性
int pthread_mutexattr_getpshared(const pthread_mutexattr_t *restrict attr , int *restrict pshared);

//用于设置互斥锁属性
int pthread_mutexattr_setpshared(pthread_mutexattr_t *attr , int pshared);

参数说明:
attr表示互斥锁属性

pshared表示互斥量的共享属性有以下两种值可取:
  PTHREAD_PROCESS_PRIVATE:锁只能用于一个进程内部的两个线程进行排斥(默认情况)。

   PTHREAD_PROCESS_SHARED:锁可用于两个不同进程中的线程进行排斥,使用还需要在共享内存中分配互斥量,然后再为互斥量指定该属性就可以了。


3. 互斥锁类型操作函数


//获取互斥锁类型
int pthread_mutexattr_gettype(const pthread_mutexattr_t *restrict attr , int *restrict type);

//设置互斥锁类型
int pthread_mutexattr_settype(const pthread_mutexattr_t *restrict attr , int type);

参数type表示互斥锁类型,总共有以下几种类型:
  1. PTHREAD_MUTEX_NORMAL:标准互斥锁,第一次上锁成功,第二次上锁会失败并阻塞。
  2. PTHREAD_MUTEX_RECURSIVE:递归互斥锁,第一次上锁成功,第二次上锁还是会成功,可以理解为内部有一个计数器,每加一次锁+1,解锁-1。
  3. PTHREAD_MUTEX_ERRORCHECK:检错互斥锁,第一次上锁会成功,第二次上锁会出错,不会阻塞
  4. PTHREAD_MUTEX_DEFAULT:默认互斥锁,第一次上锁会成功,第二次上锁会失败

4. 互斥锁类型示例

#include 
#include 
#include 
#include 

int main(int argc , char *args[]){
        //定义互斥锁
        pthread_mutex_t mutex; 
        if(argc < 2){
                printf("input mutex type\n");
                return -1;
        }
        //定义互斥锁属性
        pthread_mutexattr_t mutexattr;
        //初始化互斥锁属性
        pthread_mutexattr_init(&mutexattr);
        //设置互斥锁类型,error:检错互斥锁,normal:标准互斥锁,recursive:递归互斥锁
        if(!strcmp(args[1] , "error")){
                pthread_mutexattr_settype(&mutexattr , PTHREAD_MUTEX_ERRORCHECK);
                printf("set error succes\n");
        }else if(!strcmp(args[1], "normal")){
                pthread_mutexattr_settype(&mutexattr , PTHREAD_MUTEX_NORMAL);
                printf("set normal succes\n");
        }else if(!strcmp(args[1], "recursive")){
                pthread_mutexattr_settype(&mutexattr , PTHREAD_MUTEX_RECURSIVE);
                printf("set recursive\n");
        }
        //初始化互斥锁
        pthread_mutex_init(&mutex , &mutexattr);
        //第一次上锁
        if(pthread_mutex_lock(&mutex) != 0){
                printf("lock failed\n");
        }else{
                printf("lock succes\n");
        }
        //第二次上锁
        if(pthread_mutex_lock(&mutex) != 0){
                printf("lock failed\n");
        }else{
                printf("lock succes\n");
        }
        //加锁几次,同样也要释放几次
        pthread_mutex_unlock(&mutex);
        pthread_mutex_unlock(&mutex);
        //销毁互斥锁属性和互斥锁
        pthread_mutexattr_destroy(&mutexattr);
        pthread_mutex_destroy(&mutex);
        return 0;
}

./pthread_lock_type error,设置检错互斥锁:
31-线程属性——互斥锁类型_第1张图片

检错互斥锁第一次加锁会成功,第二次加锁会失败返回错误信息,并不会阻塞。


./pthread_lock_type normal,设置标准互斥锁:
31-线程属性——互斥锁类型_第2张图片

第一次加锁会成功,第二次加锁会失败并阻塞。


./pthread_lock_type recursive,设置递归互斥锁:
31-线程属性——互斥锁类型_第3张图片

递归互斥锁第一次加锁会成功,第二次加锁也会成功,内部会计数。

你可能感兴趣的:(linux编程修炼心法)