【多线程编程学习笔记8】使用互斥锁实现线程同步_本关任务 学会使用互斥锁来实现线程间的同步。(2)

img
img

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

我们成功地定义了一个名为 myMutex 的互斥锁,但要想使用它,还要进行初始化操作。

1) 互斥锁的初始化

初始化 pthread_mutex_t 变量的方式有两种,分别为:

//1、使用特定的宏
pthread_mutex_t myMutex = PTHREAD_MUTEX_INITIALIZER;
//2、调用初始化的函数
pthread_mutex_t myMutex;
pthread_mutex_init(&myMutex , NULL);

以上两种初始化方式是完全等价的,PTHREAD_MUTEX_INITIALIZER 宏和 pthread_mutex_init() 函数都定义在 <pthread.h> 头文件中,它们的主要区别在于:

  • pthread_mutex_init() 函数可以自定义互斥锁的属性(具体自定义的方法,这里不再进行讲解)。
  • 对于调用 malloc() 函数分配动态内存的互斥锁,只能以第 2 种方法完成初始化;

pthread_mutex_init() 函数专门用于初始化互斥锁,语法格式如下:

int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr);

mutex 参数表示要初始化的互斥锁;attr 参数用于自定义新建互斥锁的属性,attr 的值为 NULL 时表示以默认属性创建互斥锁。

pthread_mutex_init() 函数成功完成初始化操作时,返回数字 0;如果初始化失败,函数返回非零数。

注意,不能对一个已经初始化过的互斥锁再进行初始化操作,否则会导致程序出现无法预料的错误。

2) 互斥锁的“加锁”和“解锁”

对于互斥锁的“加锁”和“解锁”操作,常用的函数有以下 3 种:

int pthread_mutex_lock(pthread_mutex_t* mutex);   //实现加锁
int pthread_mutex_trylock(pthread_mutex_t* mutex);  //实现加锁
int pthread_mutex_unlock(pthread_mutex_t* mutex);   //实现解锁

参数 mutex 表示我们要操控的互斥锁。函数执行成功时返回数字 0,否则返回非零数。

pthread_mutex_unlock() 函数用于对指定互斥锁进行“解锁”操作,pthread_mutex_lock() 和 pthread_mutex_trylock() 函数都用于实现“加锁”操作,不同之处在于当互斥锁已经处于“加锁”状态时:

  • 执行 pthread_mutex_lock() 函数会使线程进入等待(阻塞)状态,直至互斥锁得到释放;
  • 执行 pthread_mutex_trylock() 函数不会阻塞线程,直接返回非零数(表示加锁失败)。
3) 互斥锁的销毁

对于使用动态内存创建的互斥锁,例如:

pthread_mutex_t myMutex = (pthread_mutex_t *)malloc(sizeof(pthread_mutex_t));pthread_mutex_init(&myMutex , NULL);

手动释放 myMutex 占用的内存(调用 free() 函数)之前,必须先调用 pthread_mutex_destory() 函数销毁该对象。

pthread_mutex_destory() 函数用于销毁创建好的互斥锁,语法格式如下:

int pthread_mutex_destroy(pthread_mutex_t *mutex);

参数 mutex 表示要销毁的互斥锁。如果函数成功销毁指定的互斥锁,返回数字 0,反之返回非零数。

注意,对于用 PTHREAD_MUTEX_INITIALIZER 或者 pthread_mutex_init() 函数直接初始化的互斥锁,无需调用 pthread_mutex_destory() 函数手动销毁。

互斥锁的实际应用

接下来,我们使用互斥锁对《线程同步机制》一节中模拟“4 个售票员卖 10 张票”的程序进行改良,如下所示:

#include<stdio.h>
#include<stdlib.h>
#include<pthread.h>
#include<unistd.h>
int ticket_sum = 10;
//创建互斥锁
pthread_mutex_t myMutex = PTHREAD_MUTEX_INITIALIZER;
//模拟售票员卖票
void *sell_ticket(void *arg) {
    //输出当前执行函数的线程 ID
    printf("当前线程ID:%u\n", pthread_self());
    int i;
    int islock = 0;
    for (i = 0; i < 10; i++)
    {
        //当前线程“加锁”
        islock = pthread_mutex_lock(&myMutex);
        //如果“加锁”成功,执行如下代码
        if (islock == 0) {
            //如果票数 >0 ,开始卖票
            if (ticket_sum > 0)
            {
                sleep(1);
                printf("%u 卖第 %d 张票\n", pthread_self(), 10 - ticket_sum + 1);
                ticket_sum--;
            }
            //当前线程模拟完卖票过程,执行“解锁”操作


![img](https://img-blog.csdnimg.cn/img_convert/8150313fab8df1cd6552029cdccb260f.png)
![img](https://img-blog.csdnimg.cn/img_convert/021f7b98e65d085b0505d2a80661c716.png)

**网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。**

**[需要这份系统化的资料的朋友,可以添加戳这里获取](https://bbs.csdn.net/topics/618658159)**


**一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**

的资料的朋友,可以添加戳这里获取](https://bbs.csdn.net/topics/618658159)**


**一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**

  • 5
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值