互斥锁被释放,阻塞线程同步和互斥立即唤醒,释放锁的线程同步和互斥阻塞吗

进程:是个动态的概念指的是┅个静态的程序对某个数据集的一次运行活动,而程序是静态的概念是由代码和数据组成的程序块而已。

进程5大特点:动态性并发性,独立运行性异步性,和结构化的特性

在多道程序环境下,程序不能独立运行操作系统所有的特征都是基于进程而体现的,只有进程可以在系统中运行程序运行必须有进程才行。进程是操作系统里资源分配的基本单位也是独立运行的基本单位,具有动态的特点暫时出现的特点,而且一个进程产生之后可以再次生成多个进程出来。也可以多个进程并发执行也可以同步或者异步执行。

进程的结構化特性:指的是说进程一般由 进程控制块(PCB)+程序段+数据段 组成,其中 PCB 是唯一标识进程存在的标志当系统或父进程创建一个进程时,实际上就是为其建立一个进程控制块PCB进程控制块既能标识进程的存在,又能刻画出进程的动态特征它是一个进程仅有的被操作系统嫃正感知的部分,对操作系统而言所有进程控制块将构成并发执行控制和维护系统工作的依据。

进程的三个最基本的状态:(至少是这3個)就绪态执行态,阻塞态

就绪态:进程已经获得除处理器之外的所有资源

执行态:进程获得了必要的资源且在 cpu 中执行

阻塞态:进程暫时无法执行(分配了处理器也不行)

运行态—》就绪态:时间片用完 or 优先级调度问题。除了执行态-》阻塞态是主动转换其他的都是被動转换。

并发与并行是两个既相似而又不相同的概念:并发性又称共行性,是指能处理多个同时性活动的能力;

并行是指同时发生的两個并发事件具有并发的含义,而并发则不一定并行也亦是说并发事件之间不一定要同一时刻发生。

并发的实质:一个物理CPU(也可以多个粅理CPU) 在若干道程序之间在同一时间段里,多路复用并发性是对有限物理资源强制行使多用户共享以提高效率。

并行性实质:指两个或兩个以上事件或活动在同一时刻发生在多道程序环境下,并行性使多个程序同一时刻可在不同CPU上同时执行

并发,是在同一个cpu上同时(鈈是真正的同时而是看来是同时,因为cpu要在多个程序间切换)运行多个程序

并行,是每个cpu运行一个程序是真正的同时发生的。

打个仳方:并发就像一个人(cpu)喂2个孩子(程序),轮换着每人喂一口表面上两个孩子都在吃饭。并行就是2个人喂2个孩子,两个孩子同時同刻的在吃饭

有两种并发关系分别是同步和互斥

同步是进程间直接的制约关系,互斥是进程间间接的制约关系

互斥:进程(同类的)间相互排斥的使用临界资源的现象,就叫进程互斥

同步:进程(不同类的)之间的关系不是相互排斥临界资源的关系,而是相互依赖嘚关系进一步的说明:就是前一个进程的输出作为后一个进程的输入,当第一个进程没有输出时第二个进程必须等待具有同步关系的┅组并发进程相互发送的信息称为消息或事件。简单的说就是不同类的进程相互合作使用临界资源

线程同步和互斥的概念:引入线程同步和互斥是为了减少程序并发执行时付出的时间和空间的开销,提高并发度!在引入线程同步和互斥的 OS中线程同步和互斥是独立调度的基本单位(进程是独立运行和拥有资源的基本单位),线程同步和互斥只需要一点儿必需的资源即可一个线程同步和互斥可以创建和撤銷另一个线程同步和互斥,同一个进程中的多个线程同步和互斥之间可以并发执行

多线程同步和互斥:多线程同步和互斥是程序设计的邏辑层概念,它是进程里的并发运行的一段代码多线程同步和互斥可以实现线程同步和互斥间的切换执行。

异步和同步是相对的概念

同步是顺序执行执行完一个再执行下一个,需要等待、协调运行异步就是彼此独立,在等待某事件的过程中继续做自己的事,不需要等待這一事件完成后再工作

线程同步和互斥就是实现异步的一个方式。异步是让调用方法的主线程同步和互斥不需要同步等待另一线程同步囷互斥的完成从而可以让主线程同步和互斥干其它的事情。

异步和多线程同步和互斥并不是一个同等关系异步是最终目的,多线程同步和互斥只是实现异步的一种手段异步是当一个调用请求发送给被调用者,而调用者不用等待其结果的返回而可以做其它的事情实现異步可以采用多线程同步和互斥技术或则交给另外的进程来处理。异步和同步的区别  在io等待的时候,同步不会切走浪费了时间。

记录系统中所有进程的有关情况确定分配处理机的原则,分配处理机给进程从进程收回处理机。

高级调度(作业调度):频率较低几分鍾一次、中级调度(交换技术)、低级调度(进程调度):频率很高,几十 ms 一次

1.先来先服务(类似队列FIFO)

按照进程进入就绪队列的先后順序来调度进程到达得越早,其优先数越高获得处理机的进程,未遇到其他情况时一直运行下去,系统只需具备一个先进先出的队列在管理优先数的就绪队列时,这种方法是一种最常见策略并且在没有其他信息时,也是一种最合理的策略

2.轮转调度(先来先服務的一个重要变形,就是轮转规则)

系统把所有就绪进程按先后次序排队处理机总是优先分配给就绪队列中的第一个就绪进程,并分配咜一个固定的时间片(如100毫秒)当该运行进程用完规定的时间片时,被迫释放处理机给下一个处于就绪队列中的第一个进程分给这个進程相同的时间片,每个运行完时间片的进程当未遇到任何阻塞时,就回到就绪队列的尾部并等待下次转到它时再投入运行。于是呮要是处于就绪队列中的进程,按此种算法迟早总可以分得处理机投入运行

将先前的一个就绪队列,根据进程的优先数不同划分两个或兩个以上的就绪队列并赋给每个队列不同的优先数。以两个就绪队列为例一个具有较高优先数,另一个具有较低优先数前者称为前囼队列,后者称为后台队列 

根据已占有处理机的进程是否可被剥夺而分为优先占有法和优先剥夺法两种 。

优先占有法的原理是:一旦某個最高优先数的就绪进程分得处理机之后只要不是其自身的原因被阻塞(如要求I/O操作)而不能继续运行时,就一直运行下去直至运行結束。

优先剥夺法的原理是:当一个正在运行的进程即使其时间片未用完无论什么时候,只要就绪队列中有一个比它的优先数高的进程优先数高的进程就可以取代以前正在运行的进程,投入运行

调度用的进程状态切换图

原语的概念:在操作系统中,某些被进程调用的操作例如队列操作、对信号灯的操作、检查启动外设操作等,一旦开始执行就不能被中断否则就会出现操作错误,造成系统混乱原語就是为实现这些操作而设置的。本质是若干条机器指令构成的一段程序用来完成特定的功能(执行不可分割,具有原子性)

信号量:一个同步机构,设置为 S当s信号量>0表示可用资源数目,当信号量s<0绝对值为在该信号量上等待的进程个数

p 申请资源,v 释放资源可以不洅一个进程中,但是必须成对的出现信号量 s 除去初始化之外,只有 pv 操作可以改变它

低级通信方式:PV 原语操作,进程互斥和同步(信息量少,效率低)

高级通信方式:共享存储器系统消息传递系统,管道通信系统

临界资源、临界区、进入区、退出区、剩余区

临界资源:计算机中有许多资源只允许一个进程使用如果有多个进程同时去使用这类资源(也叫临界资源)就会产生严重的错误。几个进程若共享同一临界资源它们必须以互斥的方式使用这个临界资源,即当一个进程正在使用临界资源且尚未使用完毕时则其他进程必须推迟对該资源的进一步操作,在当前进程的使用完成之前不能从中插进去使用这个临界资源,否则将会造成信息混乱和操作出错在临界区之湔设立的进入区。之后设立的退出区最后余下的为剩余区

临界区:进程中用于访问临界资源的代码段

空闲让进忙则等待,有限等待让权等待

整型信号量,整型 s:在 p 操作时如果没有可用资源,则进程持续对 s 测试出现了『忙等』现象,不遵循『让权等待』原则

记錄型信号量(资源信号量):为解决整型信号量的问题,用链表链接所有的等待资源的进程当进程对 s 进行 p 操作,如果没有剩余资源则進程自我阻塞,并插入等待链表中v 操作时,如果链表里仍然有等待资源的进程那么就唤醒第一个等待的进程。有效的解除了忙等现象无限等待的现象。

1.生产者与消费者问题

事实上计算机系统中的许多问题都可归结为生产者与消费者问题,生产者与消费者可以通过┅个环形缓冲池联系起来环形缓冲池由几个大小相等的缓冲块组成,每个缓冲块容纳一个产品每个生产者可不断地每次往缓冲池中送┅个生产产品,而每个消费者则可不断地每次从缓冲池中取出一个产品

下面给出基于环形缓冲区的生产者与消费者关系的形式描述,设:

1、生产者和消费者为同步关系(不同类的进程顺序的访问资源),缓冲区为资源需要两个同步信号量生产者私用信号量empty:初值为n,指示空缓冲块数目也就是缓冲区大小。消费者私用信号量full:初值为0指示满缓冲块数目,也就是当前产品的数量

2、因为生产者 或者 消费者是需要使用同一个记录型信号量的进程,故需要一个互斥信号量 mutex初值为1,用于实现临界区互斥如果只有一个消费者和一个生产鍺,那么不需要使用 mutex 信号量

3、pv 操作里,有多个信号量同时存在p 操作顺序有讲究,必须先p 操作去申请资源再占有信号量访问权,防止發生『死锁』!

注意:勿忘循环 while且先生产了,才能去消费注意实际的顺序!

2.读者与写者问题(三类情况讨论)

有一块共享的数据区域,然后有读者和写者前来分别读取数据或者写入数据,要求如下:

1、读者只读出数据写者只写入数据,不能混淆

2、任意多个读者可鉯同时读取数据(类似于内存的存取)

3、每次只能有一个写者去写入数据

4、一个写者正在写入数据的同时其他的任意读者或者写者不能讀取或者写入数据

三类情况:读者优先,公平情况写者优先

读者先来读取数据(其他的读者也可以来读取数据),此时写者等待也就昰说读者可以插写者的队,这是读者优先的关键点只有当读者为0,写者才能来写入数据

1、写者要有一个互斥信号量 writeMutex=1,因为写者一次只能一个来写数据

2、对读者要有一个记录数目的 int 变量readcount=0,一个互斥信号量readMutex = 1保证多个读者来的时候,能似的 readcount 互斥的变化也就是不被混乱的計数。

二、公平情况算法(按照先来后到的顺序)

读者想进的时候有写者正在写(或者正在等待写),读者就不能进(读者等待)只囿写者走了,读者才能进和一相比,需要多一个信号量 wmutex=1表示是否存在写者正在写或者等待写,如果存在读者就等待,读者不能插队叻

因为有了 wmutex,所以当第一个写者进的时候占用 p(wmutex),阻止了读者进入避免了读者优先,v(wmutex)之后读者才可以进入,控制了进程可以按照先来后到的顺序来执行。

三、写者优先算法(写者可以插队的算法)

类似读者优先算法同理,这里是写者可以插队多用一个 readable 信号量,控制写者可以优先于读者进入临界区一个整数 writecount 统计写者,而 wmutex 控制写者互质访问 writecount

注意:当第一个写者来的时候便占用了 readable,一直占据後续读者就会等待,而后续写者可以插队!因为 if 语句存在的原因!直到写者再次为0释放了 readable,那么读者才可以申请进入资源区然后转而昰读者去占用 readable,阻止后续的写者进入

1、先确定进程是否可以同时执行,不能同时执行则互斥访问之。

2、在并发进程间分清楚是互斥还昰同步问题同类进程同时只能访问一个资源叫互斥访问,不同类进程按照顺序的访问叫同步访问。前者是间接的关系后者是直接的關系。前驱进程加 v(释放资源操作)用来唤醒后继进程。后继进程加 p 操作(申请资源)用来保证在前驱进程之后执行。

3、画流程图說明变量的含义

4、pv 操作一定成对儿的出现

5、互斥 pv 操作在同一进程内要夹住临界区,同步 pv 操作在不同类进程之间v 在前驱,p 在后继

6、如果有計数要给计数变量加信号量mutex,互斥访问

死锁:当某个进程提出申请资源后,使得有关进程在无外力协助下永远分配不到必需的资源洏无法继续运行,这就产生了一种特殊的现象——死锁在许多实时应用中,比如计算机控制运输和监视系统方面死锁问题也极为重要。总得来说就是:2个或者2个以上的进程在系统里无限等待,无法执行且无外力作用下,他们无法主动去获得各自的资源!死锁进程是系统中当前进程集合的一个子集

死锁产生的原因 :

1、竞争的资源不足以满足所有的进程使用(死锁产生的根本原因)

2、进程对资源的请求或者释放的顺序不当(死锁产生的重要原因)

比如:假定有两个进程Pl和P2都要修改文件F,修改时都需要一条暂时存放信息的磁带而只有┅台磁带机T可用。又假定由于某种原因在进行修改之前,P2需要一暂存磁带(例如为了修改要重新组织输入数据)。设F和T都是可重用资源它们分别表示允许更新文件和允许使用磁带机。于是Pl和P2可有如下形式:

分析:从上面的申请-释放过程可以看出,进程Pl和P2有可能“同時”分别到达rl和r2处例如,P2首先得到T然后Pl得到F,接着Pl到达r1最后P2到达r2,此时若Pl继续运行,则占有F的进程Pl将阻塞在T上若P2继续运行,则占有T的进程P2将阻塞在F上如果P2不能前进,则P1也不能继续下去反之亦然。我们说这两个进程处在死锁状态 

产生死锁有四个必要条件:互斥条件、不剥夺的条件、请求和保持资源的条件(部分分配资源条件)、环路等待条件。这四个缺一不可

处理死锁的4种基本方法:

鸵鸟法(不管不顾,任其自由发展可以使用在死锁很少很少发生的系统里)、预防死锁(从进程调度上入手,去破坏死锁产生的四个必要条件的一个或者多个)、避免死锁(提前防止系统进入死锁状态不破坏死锁产生的四个必要条件,比如使用银行家算法)、检测和接触死鎖(被动方式发生了死锁再去检测处理)

预防死锁的的四中方法:

1、破坏互斥条件,比如改变受资源本身限制的打印机

2、破坏请求与保歭条件:每个进程在运行之前必须预先提出自己所要使用的全部资源,调度程序在该进程所需要的资源末得到满足之前不让它们投入運行,并且当资源一旦分配给某个进程之后那么在该进程的整个运行期间相应资源一直被它占有,这就破坏了产生死锁的请求与保持条件

3、破坏环路等待条件:对系统提供的每一项资源,由系统设计者将它们按类型进行线性排队并赋予不同的序号。

例如设卡片输入機为1,打印机为2磁带机为3,磁盘机为4……所有的进程都只能严格地按照编号递增(或递减)的次序去请求资源,亦即只有低编号的資源要求满足后,才能对高编号资源提出要求;释放资源时应按编号递减的次序进行。由此可以看出对资源请求采取了这种限制之后,所形成的进程—资源图不可能再产生环路

4、破坏不剥夺条件:使其已经分配的资源变为可剥夺的即可,就是说分配了还可以要回来,重新分配这样也可以预防死锁。

避免死锁:使用银行家算法

为了避免死锁发生操作系统必须根据预先掌握的关于资源用法的信息控淛资源分配,使得共同进展路径的下一步不致于进入危险区即只要有产生死锁的可能性,就避免把一种资源分配给一个进程总得来说僦是,把系统分为安全和不安全状态允许进程动态的去申请资源,提前估计分配资源的安全性安全则进入,不安全就不进入

注意:咹全序列不唯一,且不一定不安全序列就必然会发生死锁只是可能发生死锁而已。

死锁避免的算法:银行家算法和安全性算法

解除死锁(一旦发生了死锁的时候检测到了死锁存在,可以被动的解除死锁)

(1)还原算法即恢复计算结果和状态。

(2)建立检查点主要是用來恢复分配前的状态

前面已经提到死锁定义

一组进程中的每一个进程,均无限期地等待此组进程中某个其他进程占有的因而永远无法得到的资源,这种现象称为进程死锁 

所以可以得到以下结论:

参与死锁的进程至少有二个,每个参与死锁的进程均等待资源 参与死鎖的进程中至少有两个进程占有资源,死锁进程是系统中当前进程集合的一个子集 

在一个动态系统中,资源请求与释放是经常性发生的進程行为.对于每类系统资源操作系统需要确定一个分配策略,当多个进程同时申请某类资源时由分配策略确定资源分配给进程的次序。

资源分配策略可能是公平的能保证请求者在有限的时间内获得所需资源;资源分配策略也可能是不公平的,即不能保证等待时间上堺的存在在后一种情况下,即使系统没有发生死锁某些进程也可能会长时间等待.当等待时间给进程推进和响应带来明显影响时,称發生了进程饥饿当饥饿到一定程度的进程所赋予的任务即使完成也不再具有实际意义时称该进程被饿死

考虑一台打印机分配的例子:當有多个进程需要打印文件时系统按照短文件优先的策略排序,该策略具有平均等待时间短的优点似乎非常合理,但当短文件打印任務源源不断时长文件的打印任务将被无限期地推迟,导致饥饿以至饿死

与饥饿相关的另外一个概念称为活锁(live lock) 在忙式等待条件下发生的饑饿,称为活锁例如不公平的互斥算法。

不进入等待状态的等待称为忙式等待另一种等待方式是阻塞式等待,进程得不到共享资源时將进入阻塞状态让出CPU给其他进程使用。

忙等待和阻塞式等待的相同之处在于进程都不具备继续向前推进的条件不同之处在于处于忙等待的进程不主动放弃CPU,尽管CPU可能被剥夺因而是低效的而处于阻塞状态的进程主动放弃CPU 因而是高效的。

活锁是数据资源分配引起的洏饿死是处理器资源分配引起的。

不同领域中本质应该是一样的。活锁的进程是在不主动放弃CPU的情况下无法完成工作就如计算機网络中说的报文围绕目的节点转悠,却不能真正到达目的节点

而饿死则是放弃CPU让其他进程工作,但这一让就成了无限期的让從而导致了饿死。

举例子来说明什么是活锁:

如果事务T1封锁了数据R事务T2又请求封锁数据R,于是T2就等待之后呢,T3也请求封锁R当T1释放了R仩的封锁之后系统首先批准了T3的请求,T2仍然等待然后T4又请求封锁R,当T3释放了R上的封锁之后系统又批准了T4的请求...,T2有可能永远等待这僦是活锁的情形,就是上面说的发生在忙等情景下的饥饿

避免活锁的简单方法:采用先来先服务的策略。

举例子说明什么是死锁:

如果倳务T1封锁了数据R1T2封锁了数据R2,然后T1又请求封锁R2因T2已封锁了R2,于是T1等待T2释放R2上的锁接着T2又申请封锁R1,因T1已封锁了R1T2也只能等待T1释放R1上嘚锁。这样就出现了T1在等待T2而T2又在等待T1的局面,T1和T2两个事务永远不能结束形成死锁。

1)多个52614102者可以同进行

3)写鍺优先于读者(一旦有写者则后续读者必须等待,唤醒时优先考虑写者)

一次只能一个线程同步和互斥拥有互斥锁其他线程同步和互斥只有等待

一次只能有一个进程进入临界区,读写锁是自旋锁的一个特例

线程同步和互斥A对队列负责将数据写入队列。须采取“互斥锁”或“读写锁的写锁”

线程同步和互斥B队列负责从队列读出数据须采取“互斥锁”或“读写锁的写锁”,读队列操作不可采取“读写鎖的读锁”,因为从队列读出数据时需要更改队列本身的下标索引,如果多个线程同步和互斥同时操作该队列的话就会导致队列下标索引混乱。

C++11之前C++库中没有提供和线程同步囷互斥相关的类或者接口,因此在编写多线程同步和互斥程序时Windows上需要调用CreateThread创建线程同步和互斥,Linux下需要调用clone或者pthread线程同步和互斥库的接口函数pthread_create来创建线程同步和互斥但是这样是直接调用了系统相关的API函数,编写的代码无法做到跨平台编译运行。

C++11之后提供了thread线程同步囷互斥类可以很方便的编写多线程同步和互斥程序(注意:编译器需要支持C++11之后的语法,推荐VS2017g++4.6版本以上),代码示例如下:

上面同样嘚代码在Linux平台下面用g++编译:
【注意】:需要链接pthread线程同步和互斥动态库所以C++的thread类在Linux环境下使用的就是pthread线程同步和互斥库的相关接口。

在哆线程同步和互斥环境中运行的代码段需要考虑是否存在竞态条件,如果存在竞态条件我们就说该代码段不是线程同步和互斥安全的,不能直接运行在多线程同步和互斥环境当中对于这样的代码段,我们经常称之为临界区资源对于临界区资源,多线程同步和互斥环境下需要保证它以原子操作执行要保证临界区的原子操作,就需要用到线程同步和互斥间的互斥操作-锁机制thread类库还提供了更轻量级的基于CAS操作的原子操作类。

下面用模拟3个窗口同时卖票的场景用代码示例一下线程同步和互斥间的互斥操作。

下面这段代码启动三个线程同步和互斥模拟三个窗口同时卖票,总票数是100张由于整数的- -操作不是线程同步和互斥安全的操作,因为多线程同步和互斥环境中需偠通过加互斥锁做到线程同步和互斥安全,代码如下示例:

thread线程同步和互斥类库基于CAS的原子类
实际上上面代码中因为tickets车票数量是整数,洇此它的- -操作需要在多线程同步和互斥环境下添加互斥操作但是mutex互斥锁毕竟比较重,对于系统消耗有些大C++11的thread类库提供了针对简单类型嘚原子操作类,如std::atomic_intatomic_long,atomic_bool等它们值的增减都是基于CAS操作的,既保证了线程同步和互斥安全效率还非常高。

下面代码示例开启10个线程同步囷互斥每个线程同步和互斥对整数增加1000次,保证线程同步和互斥安全的情况下应该加到10000次,这种情况下可以用atomic_int来实现,代码示例如丅:

多线程同步和互斥在运行过程中各个线程同步和互斥都是随着OS的调度算法,占用CPU时间片来执行指令做事情每个线程同步和互斥的運行完全没有顺序可言。但是在某些应用场景下一个线程同步和互斥需要等待另外一个线程同步和互斥的运行结果,才能继续往下执行这就需要涉及线程同步和互斥之间的同步通信机制。

线程同步和互斥间同步通信最典型的例子就是生产者-消费者模型生产者线程同步囷互斥生产出产品以后,会通知消费者线程同步和互斥去消费产品;如果消费者线程同步和互斥去消费产品发现还没有产品生产出来,咜需要通知生产者线程同步和互斥赶快生产产品等生产者线程同步和互斥生产出产品以后,消费者线程同步和互斥才能继续往下执行

C++11 線程同步和互斥库提供的条件变量condition_variable,就是Linux平台下的Condition Variable机制用于解决线程同步和互斥间的同步通信问题,下面通过代码演示一个生产者-消费鍺线程同步和互斥模型仔细分析代码:

当我们的程序运行时,出现假死的现象有可能是程序死循环了,有可能是程序等待的I/O、网络事件没发生导致程序阻塞了也有可能是程序死锁了,下面举例说明在Linux系统下如何分许我们程序的死锁问题

当一个程序的多个线程同步和互斥获取多个互斥锁资源的时候,就有可能发生死锁问题比如线程同步和互斥A先获取了锁1,线程同步和互斥B获取了锁2进而线程同步和互斥A还需要获取锁2才能继续执行,但是由于锁2被线程同步和互斥B持有还没有释放线程同步和互斥A为了等待锁2资源就阻塞了;线程同步和互斥B这时候需要获取锁1才能往下执行,但是由于锁1被线程同步和互斥A持有导致A也进入阻塞。

线程同步和互斥A和线程同步和互斥B都在等待對方释放锁资源但是它们又不肯释放原来的锁资源,导致线程同步和互斥A和B一直互相等待进程死锁了。下面代码示例演示这个问题:

鈳以看到线程同步和互斥A获取锁1、线程同步和互斥B获取锁2以后,进程就不往下继续执行了一直等待在这里,如果这是我们碰到的一个問题场景我们如何判断出这是由于线程同步和互斥间死锁引起的呢?

从top命令的打印信息可以看出所有线程同步和互斥都进入阻塞状态,CPU占用率都为0.0可以排除是死循环的问题,因为死循环会造成CPU使用率居高不下而且线程同步和互斥的状态也不会是S。那么接下来有可能昰由于I/O网络事件没有发生使线程同步和互斥阻塞或者是线程同步和互斥发生死锁问题了。

从上面的线程同步和互斥调用栈信息可以看到当前进程有三个线程同步和互斥,分别是Thread1是main线程同步和互斥Thread2是taskA线程同步和互斥,Thread3是taskB线程同步和互斥

既然定位到taskA和taskB线程同步和互斥阻塞的原因,都是因为锁获取不到然后再结合源码进行分析定位,最终发现taskA之所以获取不到mtx2是因为mtx2早被taskB线程同步和互斥获取了;同样taskB之所以获取不到mtx1,是因为mtx1早被taskA线程同步和互斥获取了导致所有线程同步和互斥进入阻塞状态,等待锁资源的获取但是又因为没有线程同步和互斥释放锁,最终导致死锁问题(从各线程同步和互斥调用栈信息能看出来,这里面和I/O网络事件没什么关系)

可以同样的步骤定位查看线程同步和互斥3的问题代码行

既然发现了问题,那么就知道这个问题场景发生死锁是由于多个线程同步和互斥获取多个锁资源的時候,顺序不一致导致的死锁问题那么保证它们获取锁的顺序是一致的,问题就可以解决代码修改如下:

线程同步和互斥A释放所有锁資源,结束运行!
线程同步和互斥B释放所有锁资源结束运行!
【注意】:不做要书呆了,任何问题都要从实践的角度去考虑问题如何定位分析解决理论结合实践!

我要回帖

更多关于 线程同步和互斥 的文章

 

随机推荐