九、Linux下线程互斥锁类型及属性

一、互斥锁的创建和销毁

pthread_mutexattr_t是互斥锁属性的数据类型,表示互斥锁的一些属性相关的信息。
使用 pthread_mutexattr_init 可以将与互斥锁对象相关联的属性初始化为其缺省值。在执行过程中,线程系统会为每个属性对象分配存储空间。

#inlcude<pthread.h>
//初始化互斥锁属性
pthread_mutexattr_init(pthread_mutexattr_t attr);

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

//使用方法
/*定义互斥锁属性*/
pthread_mutexattr_t     mutexattr;
/*初始化互斥锁属性*/
pthread_mutexattr_init(&mutexattr);
  • 函数参数:
    attr:互斥锁属性
  • 返回值:
    成功返回0,出错返回错误编号

ret = pthread_mutexattr_init(&mattr);
调用此函数时,pshared 属性的缺省值为 PTHREAD_PROCESS_PRIVATE。该值表示可以在进程内使用经过初始化的互斥锁。

mattr 的类型为 opaque,其中包含一个由系统分配的属性对象。mattr 范围可能的值为 PTHREAD_PROCESS_PRIVATE 和PTHREAD_PROCESS_SHARED。PTHREAD_PROCESS_PRIVATE 是缺省值。

对于互斥锁属性对象,必须首先通过调用 pthread_mutexattr_destroy将其销毁,才能重新初始化该对象。pthread_mutexattr_init() 调用会导致分配类型为 opaque 的对象。如果未销毁该对象,则会导致内存泄漏。

二、互斥锁进程共享属性获取及设置

1. 设置互斥锁范围

pthread_mutexattr_setpshared可用来设置互斥锁变量的作用域。

#include <pthread.h>
int	pthread_mutexattr_setpshared(pthread_mutexattr_t *mattr,int pshared);
 
//使用方法
int ret;
pthread_mutexattr_t mattr;
ret = pthread_mutexattr_init(&mattr);
/*
 * resetting to its default value: private
 */
ret = pthread_mutexattr_setpshared(&mattr,PTHREAD_PROCESS_PRIVATE);
  • 函数参数:
    attr:互斥锁属性
  • pshared:进程共享属性
    • PTHREAD_PROCESS_PRIVATE(默认情况)锁只能用于一个进程内部的两个线程进行互斥
    • PTHREAD_PROCESS_SHARED锁可以用于两个不同进程中的线程进行互斥
  • 返回值:成功返回0,出错返回错误编号
2. 获取互斥锁范围

pthread_mutexattr_getpshared可用来返回由 pthread_mutexattr_setpshared() 定义的互斥锁变量的范围。

#include <pthread.h>
int	pthread_mutexattr_getpshared(pthread_mutexattr_t *mattr,int *pshared);
 
 //使用方法
int pshared, ret;
pthread_mutexattr_t mattr;
/* get pshared of mutex */
ret = pthread_mutexattr_getpshared(&mattr, &pshared); 
  • 此函数可为属性对象 mattr 获取 pshared 的当前值。该值为 PTHREAD_PROCESS_SHARED 或 PTHREAD_PROCESS_PRIVATE。
  • 返回值:成功返回0,出错返回错误编号

三、互斥锁类型的操作

1. 设置类型

pthread_mutexattr_settype可用来设置互斥锁的 type 属性。

#include <pthread.h>
int pthread_mutexattr_settype(pthread_mutexattr_t  *attr , int type);

类型属性的缺省值为 PTHREAD_MUTEX_DEFAULT。

  1. 函数参数:
    attr:互斥锁属性

  2. type 参数指定互斥锁的类型。以下列出了有效的互斥锁类型:

  • PTHREAD_MUTEX_NORMAL:标准互斥锁:第一次上锁成功,第二次上锁会阻塞。
    描述:
    此类型的互斥锁不会检测死锁。如果线程在不首先解除互斥锁的情况下尝试重新锁定该互斥锁,则会产生死锁。尝试解除由其他线程锁定的互斥锁会产生不确定的行为。如果尝试解除锁定的互斥锁未锁定,则会产生不确定的行为。
  • PTHREAD_MUTEX_ERRORCHECK:检错互斥锁:第一次上锁成功,第二次上锁会出错。
    描述:
    此类型的互斥锁可提供错误检查。如果线程在不首先解除锁定互斥锁的情况下尝试重新锁定该互斥锁,则会返回错误。如果线程尝试解除锁定的互斥锁已经由其他线程锁定,则会返回错误。如果线程尝试解除锁定的互斥锁未锁定,则会返回错误。
  • PTHREAD_MUTEX_RECURSIVE:递归互斥锁:第一次上锁成功,第二次上锁也会成功,内部计数。
    描述:
    如果线程在不首先解除锁定互斥锁的情况下尝试重新锁定该互斥锁,则可成功锁定该互斥锁。 与 PTHREAD_MUTEX_NORMAL 类型的互斥锁不同,对此类型互斥锁进行重新锁定时不会产生死锁情况。多次锁定互斥锁需要进行相同次数的解除锁定才可以释放该锁,然后其他线程才能获取该互斥锁。如果线程尝试解除锁定的互斥锁已经由其他线程锁定,则会返回错误。 如果线程尝试解除锁定的互斥锁未锁定,则会返回错误。
  • PTHREAD_MUTEX_DEFAULT:默认互斥锁:同标准的互斥锁
    描述:
    如果尝试以递归方式锁定此类型的互斥锁,则会产生不确定的行为。对于不是由调用线程锁定的此类型互斥锁,如果尝试对它解除锁定,则会产生不确定的行为。对于尚未锁定的此类型互斥锁,如果尝试对它解除锁定,也会产生不确定的行为。允许在实现中将该互斥锁映射到其他互斥锁类型之一。

3.返回值:
成功返回 0, 出错返回错误编号

2.获取类型

pthread_mutexattr_gettype 可用来获取由 pthread_mutexattr_settype() 设置的互斥锁的 type 属性。

#include <pthread.h>
int pthread_mutexattr_gettype(pthread_mutexattr_t  *attr , int  *type);

类型属性的缺省值为 PTHREAD_MUTEX_DEFAULT。

1.函数参数:
attr:互斥锁属性
2. type 参数指定互斥锁的类型。有效的互斥锁类型包括:

  • PTHREAD_MUTEX_NORMAL
  • PTHREAD_MUTEX_ERRORCHECK
  • PTHREAD_MUTEX_RECURSIVE
  • PTHREAD_MUTEX_DEFAULT
    有关每种类型的说明,请参见pthread_mutexattr_settype 语法。

3.返回值:
成功返回 0, 出错返回错误编号

四、案例

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
int main(int argc,char* argv[])
{
        //定义互斥锁类型
        pthread_mutex_t mutex;
        //判断是否有参数传来
        if(argc<2)
        {
                printf("-usrage:[error|normal|recursive]\r\n");
                exit(1);
        }
        //定义互斥锁属性
        pthread_mutexattr_t mutexattr;
        //初始化互斥锁属性
        pthread_mutexattr_init(&mutexattr);

        //根据外部的输入设置互斥锁的类型
        if(!strcmp(argv[1],"error"))
        {
                pthread_mutexattr_settype(&mutexattr,PTHREAD_MUTEX_ERRORCHECK);
        }
        else if(!strcmp(argv[1],"normal"))
        {
                pthread_mutexattr_settype(&mutexattr,PTHREAD_MUTEX_NORMAL);
        }
        else if(!strcmp(argv[1],"recursive"))
        {
                pthread_mutexattr_settype(&mutexattr,PTHREAD_MUTEX_RECURSIVE);
        }
        //初始化互斥锁
        pthread_mutex_init(&mutex,&mutexattr);
        //第一次上锁
        if(pthread_mutex_lock(&mutex)!=0)
        {
                printf("Lock failure\r\n");
        }else
        {
                printf("Lock success\n");
        }
        //第二次上锁
        if(pthread_mutex_lock(&mutex)!=0)
        {

                printf("Lock failure\r\n");
        }else
        {

                printf("Lock success\n");
        }
        //上几次锁,解几次锁
        pthread_mutex_unlock(&mutex);
        pthread_mutex_unlock(&mutex);

        //销毁线程的互斥锁属性以及互斥锁
        pthread_mutexattr_destroy(&mutexattr);
        pthread_mutex_destroy(&mutex);
}

从下图的结果来看:
当互斥锁的类型是检错类型时,第一次上锁成功,第二次上锁会失败。
当互斥锁类型是标准类型时,第一次上锁成功,第二次上锁会阻塞。
当互斥锁类型是递归类型时,第一次上锁成功,第二次上锁也会成功。
在这里插入图片描述
**
补充学习:
int main(int argc, char* argv[])
argc是命令行总的参数个数(包括程序的全名)
argv[]是argc个参数,其中第0个参数是程序的全名,以后的参数 命令行后面跟的用户输入的参数。
**

#include <stdio.h>

int main(int argc,char* argv[])
{
	int i=0;
	for(i=0;i<argc;i++)
	printf("%s\r\n",argv[i]);
	return 0;
}

在这里插入图片描述

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值