Young87

当前位置:首页 >个人收藏

互斥锁(使用过程及应用场景)

互斥锁使用流程

定义互斥锁变量

pthread_mutex_t:互斥锁变量的类型
    例:pthread_mutex_t mutex

初始化互斥锁变量

int pthread_mutex_init(pthread_mutex_t* mutex, const pthread_mutexattr_t* attr);
    muter:互斥锁变量,传参数的时候,传入互斥锁变量的地址
    attr:互斥锁属性,一般情况下,我们都不需要关心,直接设置为 NULL
pthread_mutex_t mutex = PTHREAD_MUTEX_INTIALIZER;
    PTHREAD_MUTEX_INTIALIZER:宏定义,里面对结构体进行可宏定义,使用这种方式进行初始化的时候,其实是将结构体当中变量的值复制给互斥锁变量

加锁

int pthread_mutex_lock(pthread_mutex_t* mutex);
    mutex:互斥锁变量,传参数的时候,传入互斥锁变量的地址
    使用该接口进行加锁的时候
        如果临界资源可用,意味着互斥锁变量当中计数器的值为 1,可以进行加锁,对计数器的值进行减 1操作,加锁成功,执行流继续向下执行
        如果临界资源不可用,阻塞等待,执行流不会继续向下执行
int pthread_mutex_trylock(pthread_mutex_t* mutex);
    mutex:互斥锁变量,使用的时候,传入互斥锁变量的地址
        如果临界资源可用,意味着互斥锁变量当中计数器的值为 1,可以进行加锁,对计数器的值进行减 1操作,加锁成功,执行流继续向下执行
        如果临界资源不可用,不会进行阻塞等待,pthread_mutex_trylock 加锁失败,返回 BUSY(拿不到锁资源)
 int pthread_mutex_timedlock(pthread_mutex_t* mutex, const struct timespec* abs_timeout);
     mutex:互斥锁变量
     abs_timeout:加锁的超时时间
         当超过加锁的超时时间之后,还没有获取到互斥锁,就报错返回,不会再进行阻塞等待,返回 ETIMEOUT
     struct timespec 当中有两个参数,第一个参数是秒,第二个参数为纳秒

解锁

int pthread_mutex_nulock(pthread_mutex_t* mutex);
     mutex:互斥锁变量,使用的时候,传入互斥锁变量的地址
     三种加锁方式都可以用这种方式解锁

销毁

 int pthread_mutex_destroy(pthread_mutex_t* mutex);
       mutex:互斥锁变量,使用的时候,传入互斥锁变量的地址
       如果不调用销毁接口,会造成内存泄漏

互斥锁加锁解锁示意

在这里插入图片描述

互斥锁应用

抢票程序,需要考虑四个问题:

  1. 初始化位置
    创建线程之前
  2. 加锁位置
    访问资源之前
  3. 未解锁的后果
    造成所有想要加该锁的线程都进入阻塞状态,这也是死锁之一的情况
  4. 解锁位置
    在所有有可能退出的地方都需要进行解锁
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
#include <sched.h>
int ticket = 100;
pthread_mutex_t mutex;
void *route(void *arg) {
    char *id = (char*)arg;
    while ( 1 ) {
        pthread_mutex_lock(&mutex);//加锁位置
        if ( ticket > 0 ) {
            usleep(1000);
            printf("%s sells ticket:%d\n", id, ticket);
            ticket--;
            pthread_mutex_unlock(&mutex);//解锁位置
            // sched_yield(); 放弃CPU
       } else {
            pthread_mutex_unlock(&mutex);//解锁位置
            break;
       }
   }
}
int main( void )
{
    pthread_t t1, t2, t3, t4;
    pthread_mutex_init(&mutex, NULL);//初始化位置
    pthread_create(&t1, NULL, route, "thread 1");
    pthread_create(&t2, NULL, route, "thread 2");
    pthread_create(&t3, NULL, route, "thread 3");
    pthread_create(&t4, NULL, route, "thread 4");
    pthread_join(t1, NULL);
    pthread_join(t2, NULL);
    pthread_join(t3, NULL);
    pthread_join(t4, NULL);
    pthread_mutex_destroy(&mutex);//销毁位置
}

除特别声明,本站所有文章均为原创,如需转载请以超级链接形式注明出处:SmartCat's Blog

上一篇: HTML_first_复习

下一篇: 如何实现简单的人脸检测—基于Haar特征提取的Adaboost强化分类器实现

精华推荐