学习系统编程No.32【线程互斥实战】

这篇具有很好参考价值的文章主要介绍了学习系统编程No.32【线程互斥实战】。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

引言:

北京时间:2023/7/19/15:22,昨天更新完博客,和舍友下了一会棋,快乐就是这么简单,哈哈哈!总体来说,摆烂程度得到一定的改善,想要达到以前的水准,需要一定的契机,毕竟人生在世,快乐最重要是吧!更文带给我的快乐已经没有那么多了,虽然欠了非常多的作业,非常多的课需要补,很多的题等着我去刷,怎叹一个懒字了得,本质还是作息控制不住,哎!这周小目标更文4篇,只要能达到这个水准,其它的都好说,想到还有那么多课没有看,现在真的挺头疼!不管那么多,正式进入该篇博客的正题,承接上篇博客有关多线程互斥和同步相关的知识,该篇博客我们继续深入理解一下有关线程的互斥和同步吧!

学习系统编程No.32【线程互斥实战】,深入理解计算机系统,学习,java,开发语言

深入线程互斥

承接上篇博客有关线程互斥相关知识,此时我们在深入理解一下线程互斥。在上篇博客中,我们重点强调了为什么要进行线程互斥和如何进行线程互斥,也就是如何让一份共享资源变为临界资源,每次访问共享资源时,只能有一个线程获得资源的使用权(加锁),其他线程必须等待,直到该线程释放资源后才能继续执行(解锁)。并且在此基础上,我们还简单介绍了有关线程互斥的相关线程库接口,如:pthread_mutex_init,pthread_mutex_lock,pthread_mutex_unlock,pthread_mutex_destroy ,当然我们也明白,在使用这些线程互斥接口的前提是我们定义了一个全局的锁,pthread_mutex_t mutex; 在使用文档中,当我们定义了一个全局的锁结构时,该锁结构是一定需要进行初始化和销毁,也就是必须使用pthread_mutex_init接口和pthread_mutex_destroy,但是使用文档中也给我们提供了另一种方法,让我们可以不需要使用这两个接口,就能完成锁结构的初始化和销毁,在定义锁结构时直接在其后面添加对应的宏结构,pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;这样就可以直接在定义锁的同时,完成对锁的初始化和最终锁的销毁,更简便的供给我们使用。那么此时有的同学就会有问题了,有了这个宏定义,还需要之前初始化和销毁的接口干嘛呢?答案是,使用宏定义快速对锁进行初始化的前提是该锁是一个全局变量的锁,只有是全局变量的锁才有资格使用pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;方法,因为如果对应的锁是局部变量,那么就会导致当函数调用完之后,对应的局部变量锁随着栈帧的销毁而销毁,最终导致编译器无法根据地址再找到对应的锁结构,造成资源泄露问题,所以当定义一个局部变量的锁时,此时就只能使用pthread_mutex_init接口和pthread_mutex_destroy接口进行对应的初始化和销毁。当然此时还没有讲清楚,为什么局部变量不能用 PTHREAD_MUTEX_INITIALIZER方法,只有全局变量可以,这是因为如果使用了 PTHREAD_MUTEX_INITIALIZER方法,本质是将对应的锁变量初始化为默认值,并且将其存储在静态区中,使其生命周期与该进程的声明周期相同,当进程结束,操作系统就会自动回收该锁变量占用的资源,达到销毁目的,所以这也就是为什么局部变量锁不能使用 PTHREAD_MUTEX_INITIALIZER方法的原因。

互斥锁细节介绍
搞定了上述知识,此时我们对锁就有了进一步的理解,当然想要彻底搞定锁相关的知识,重点是搞定锁的实现原理,明白它为什么可以让共享资源变成临界资源,不过在了解锁实现原理之前,此时我们先来谈谈有关加锁方面的细节知识,如:一个共享资源只允许使用一把锁进行保护,不然就有可能导致死锁问题。并且在进行加锁时,加锁的位置一定要合理,尽量细化,只要将共享资源保护起来就行,不允许大范围加锁,否则会导致代码执行效率非常低。然后还要明白,对于锁来说,加锁和解锁本身就是一个原子结构,也就是因为锁也属于共享资源,如果不对锁进行保护的话,那么同理会导致竞态条件问题,所以锁的设计者在设计锁的时候,已经将锁设计为原子结构,也就是当一个线程在访问一个锁的时候,别的线程不允许访问该锁。最后还要明白,一个临界区不仅仅只是一行代码,也可能是一批代码,所以当某个线程在执行该临界区中的代码时,该线程有可能会因为时间片到了,而被操作系统调度,使得对应临界区中的代码没有执行完,但是这并不会导致其它线程可以访问对应的临界资源,因为加锁之后,无论临界区的代码是否执行完毕,其它线程都无法访问到对应的临界资源,这也正是加锁之后带来的线程串行化表现。

锁的基本实现原理
搞定了上述知识,我们正式进入锁的实现原理讲解,首先明白,锁本质就是一个互斥量,因为其可以保护共享资源,也就是只让一个线程访问对应的资源,所以我们将这种特性(互斥)称之为锁,也叫互斥锁。明白了这点之后,接下来我们要搞定的也就是互斥量如何进行互斥,从而让多个线程访问共享资源时,只有一个线程能够成功访问,如下图所示:

学习系统编程No.32【线程互斥实战】,深入理解计算机系统,学习,java,开发语言

如上图所示,此时我们明白,对于所有线程来说,它们在同时访问同一份共享资源时,因为我们进行了加锁操作(pthread_mutex_lock),所以它们在访问该共享资源之前就需要执行加锁接口相关的代码,也就是如上图所示的伪代码,首先它们要将自己上下文中的%al变量初始化为0,然后再使用exchange接口将我们事先定义并且初始化好的锁变量(mutex)从内存中交换到寄存器,也就是交换到自己的上下文中,让%al由0变1,让mutex由1变0,完成了这一步骤之后,对应的线程就实现了互斥操作,也就是我们所说的加锁,并且此时mutex就是该互斥操作中的互斥量。交换的目的就是让这个互斥量只被一个线程拿到,当下一个线程也要交换时,由于mutex互斥量已经变为了锁定状态(0),此时它就无法获取到mutex中的1(未锁定状态),从而无法执行pthread_mutex_lock中的后序代码,只能被操作系统挂起等待(if语句判断)。最后明白一点,也就是我们一直说的锁是共享资源,却不会造成竞态条件的原因是因为其设计成了原子性,从上图我们就能看出,一个线程在执行对应加锁代码时,其中获取互斥量的过程,仅仅就只是一个交换语句,所以可以明白,对于线程来说,单独一句代码,要么执行,要么就是不执行,所以对于加锁操作,它天生就是原子性的。

所以同理解锁操作,就是将mutex的值由0变1,这样,下一个线程在执行加锁操作时,就可以获取到对应mutex互斥量中的1,因为此时mutex处于未锁定状态(1),同理获取到之后(交换)mutex就又会处于锁定状态(0),所以这也是为什么有加锁操作,就一定要有解锁操作,否则就会造成死锁,无论是那个线程都无法访问到该共享资源。

线程封装

明白了上述有关互斥锁的相关知识之后,此时我们进行线程的封装,也就是对pthread.h头文件中有关线程控制相关接口的封装,实现一个自己的简易线程库,当然无论是在C++,还是Java中,它们的线程库都是和我们一样,对pthread.h头文件进行的封装,只不过在设计上不同,所以导致不同的语言在线程库的使用上不同,本质原因就是封装的方法不同,如下代码所示,就是我们自己对线程库的一个封装:

学习系统编程No.32【线程互斥实战】,深入理解计算机系统,学习,java,开发语言

如上图所示,此时我们就使用Thread类,完成了对线程库的一个简易封装,重点就是注意参数类型和函数指针传参方面的问题,并且还要注意有关静态成员函数相关的知识,也就是如果在一个类中,你因为参数的原因,无法使用this指针,那么此时你就可以使用静态成员函数,使用static声明,这样就完成了该成员函数和类之间的解耦,但是,因为你将该成员函数和类解耦,所以也就导致该成员函数没有this指针,最终导致该成员函数无法访问到类中的成员变量,具体如何解耦这里我们不详谈,这里注意,明白会用就行。

互斥锁的封装

明白了上述有关线程库的封装,此时我们再来看看有关互斥锁的封装,当然此时的封装还是同理对系统接口进行封装,而不是对伪代码进行封装,本质就是为了让我们可以更方便的使用加锁和解锁,如下代码所示:

学习系统编程No.32【线程互斥实战】,深入理解计算机系统,学习,java,开发语言

此时我们就完成了对锁的封装,那么此时有的同学就会问了,为什么要这样对锁进行封装呢?如下代码所示:本质就是为了让加锁和解锁操作变得更加简易

学习系统编程No.32【线程互斥实战】,深入理解计算机系统,学习,java,开发语言
如上图所示,通过两种不同的加锁和解锁操作,我们发现,如果将加锁和解锁操作封装在一个类的构造和析构函数中,然后通过对该类对象进行传参,这样可以非常方便的完成对共享资源的保护。文章来源地址https://www.toymoban.com/news/detail-602590.html

总结:有关线程互斥,互斥锁的基本原理和封装,有关线程等相关知识我们就讲到这里啦!更多有关线程互斥与同步的知识,我们下篇博客见。

到了这里,关于学习系统编程No.32【线程互斥实战】的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 学习系统编程No.25【核心转储实战】

    北京时间:2023/6/16/8:39,实训课中,大一下学期最后有课的一天,还有两天就要期末考啦!目前什么都还没有复习,不到星期天晚上,咱不慌,小小挂科,岂能拦得住我补考,哈哈哈!小事,莫慌,该篇博客出炉之时,就是我复习之日,临阵磨枪不快也光,这方面我是专业的

    2024年02月11日
    浏览(46)
  • 学习系统编程No.26【信号处理实战】

    北京时间:2023/6/26/13:35,昨天12点左右睡觉,本以为能和在学校一样,7点左右起床,设置了7点到8点30时间段内的4个闹钟,可惜没想到啊,没醒,直接睡到了12点,看来下次不能给自己太高的期望,哈哈哈!在家没办法呀,习惯睡到12点了,想要解决这个问题,最好的方法就是

    2024年02月11日
    浏览(45)
  • 学习系统编程No.30【多线程控制实战】

    北京时间:2023/7/7/9:58,耳机正在充电中,所以刚好让我们先把引言写一写,昨天睡觉前听了一会小说,听小说的好处就在于,它可以让你放下手机,快速睡觉,并且还有一定的助眠效果,但是最近有点书荒,所以听小说不是很积极,平时睡觉也就控制不住,昨天把很久以前看

    2024年02月15日
    浏览(44)
  • 学习系统编程No.18【进程间通信之管道实战】

    北京时间:2023/4/11/21:17,今天的文章更新啦!但是还是没有上热榜,所以我们需要继续更文啦!我相信下一篇博客肯定是可以上热榜的,加油!并且今天晚上因为有一节体育课,所以导致现在才开始码字,体育课上教我们打羽毛球,虽然我自从高考到现在已经快一年没打了,

    2024年02月02日
    浏览(35)
  • 【Linux操作系统】多线程抢票逻辑——学习互斥量(锁)函数接口

    临界资源 : 多线程执行流共享的资源就叫做临界资源 。 临界区 :每个线程内部, 访问临界资源的代码,就叫做临界区 。 互斥 :任何时刻, 互斥保证有且只有一个执行流进入临界区,访问临界资源,通常对临界资源起保护作用 。 原子性 :不会被任何调度机制打断的操作

    2024年02月16日
    浏览(43)
  • 学习系统编程No.13【文件系统】

    北京时间:2023/3/31/7:48,该篇博客在两天前本就应该产出,但是摆烂谁拦得住,所以呜呜呜!本以为欠的钱也要快还完了,没想到啊,越欠越多,烦人!但是,欠的都是小钱,不像以前,欠的是大钱,所以也不怎么打紧,慢慢还啦!这周的榜估计是保不住了,具体还要看看周

    2023年04月15日
    浏览(72)
  • 学习系统编程No.24【深入学习信号】

    北京时间:2023/6/13/19:07,伴随着期末考的来临,最近停课啦!无论是线上课,还是学校的课,开心,那这不是咱持续更文的好时候嘛,但是今天在学习相关C++知识时,涉及到了线程相关知识,虽然能听,但是听起来就比较费劲,所以我们要先暂停C++相关知识的学习,转而投向

    2024年02月09日
    浏览(38)
  • 学习系统编程No.7【进程替换】

    北京时间:2023/3/21/7:17,这篇博客本来昨天晚上就能开始写的,但是由于笔试强训的原因,导致时间用在了做题上,通过快2个小时的垂死挣扎,我充分意识到了自己做题能力的缺陷和运用新知识的缺陷,所以我需要把重心给转移一下了,以后做题才是我的头号目标,虽然我在

    2024年02月21日
    浏览(39)
  • 学习系统编程No.14【动静态库】

    北京时间:2023/4/3/7:06,刚刚晨跑回来,为了摆脱困意,刷了一下视屏,哈哈哈!我发现我每次刷视屏都是被迫的,都是看到某个感兴趣的标题,然后点进去一看,就不能自拔了,所以我下次得把消息提醒给全部关掉,烦人;并且全宿舍英文4级都报上了,就我没报上,真的是

    2023年04月09日
    浏览(53)
  • 学习系统编程No.16【进程间通信】

    北京时间:2023/4/9/20:44,昨天,也就是这个周末的星期六,就是传说中的蓝桥杯,哈哈哈!摆烂,做题方面真不怎么行,可惜,当初可能是年少轻狂或者说是没什么经验阅历,希望在有了这次的经历之后,明年的今天,能够更加从容吧!谁让我们平时不怎么做题呢?准确的来

    2023年04月15日
    浏览(47)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包