两个线程能在cpu中同时运行吗_操作系统中的线程、锁机制和PV操作

1b16f180a84eaad72c1a439b8c53a612.png

论处于考试周的学生现状:论文肝到底,天天push,坐在电脑前就是一整天,只要还有一个根头发,都不能阻挡我肝的步伐。终于,等到最后一门结束时,我发出了脱缰野马般的咆哮~~~

哈喽,各位老铁,我又带着干货来啦。

操作系统中的线程、锁机制和PV操作

01

线程

线程是可由CPU直接运行的实体,是程序中的执行路径,一个进程可以创建多个线程,多个线程共享CPU可以实现并发运行。同时线程的并发粒度比进程的并发粒度更细。

单线程程序

整个进程中只有一个线程。Window程序缺省只有一个线程(主线程,main线程)

多线程程序

整个进程中至少有两个线程。主线程和至少一个用户线程。

线程技术的典型应用场景

程序的多个功能需要并发运行

在线视频:

04dc5dfdb6616bf9206ed11fa15e5380.png

并发的功能:视频的解码、音频的解码,网络接受,显示和播放音视频等等,这些都需要并发运行,才能给我们良好的体验感和沉浸感。

Microsoft Windows的文件拷贝程序是个多线程程序

51e54eed1c74f8d420aeac105052cc5f.png

多核心CPU上的应用,利用多线程可以更好的发挥多核性能

 使用多线程的麻烦事儿

44e56baf06ae9c2448f179f37207e415.png

虽然使用线程可以帮我们解决很多问题,线程也存在着一些问题,需要克服,第1个就是一个程序来说,如果单线程程序来说程序是依次往下运行的,逐行逐行的,往下运行的,如果是多线程程序,那么程序的运行是并发的,所以这个程序在调试的时候,它就不一定是按照这个我们预想的一行一行的运行,过程难以控制,同时存在那么多个并发运行的线程,多线程可能会同时对这个共享变量进行一个程序操作,会不会多个线程的同时来访问?这就回带来很多的麻烦事儿;另外就是线程的安全问题。

02

临界区

临界区和临界资源

并发错误:对于一个内存全局变量k,有程序a和程序b如下:

程序A:...k = 100;...printf("A : k = %d",k);......
程序B:...k = 200;...printf("B : k = %d",k);......


如果两个程序并发运行,两个程序的打印结果是不确定的,既可以是100也可以是200。
假设程序A在执行 ``printf()`` 语句之前由于需要其他操作,暂时停止运行,而程序B无阻碍的运行,就会在程序A打印变量 ``k``之前将其值修改为200,进而使得程序A的打印结果不再是理论上的100.这就会出现程序的并发错误。

e3b6f6c3104398b96374c330dd345f55.png

那有什么好的解决方案吗?

97d77a9443466f7f114f68662a489490.png

答案:程序设定一个特定的区域不让两个程序同时进入运行,只能先后进入。

13a969ec91402e590820274640458129.png

临界资源

一次只允许一个进程独占访问和使用的资源(如内存中的共享变量)

临界区

进程中访问临界资源的程序段

临界区和临界资源的访问特点

1.具有排他性
2.并发进程不能进入到临界区

设计临界区访问机制的原则

既然临界区对程序能够正确地并发运行很重要,那么在操作系统中,就需要设计出合理而高效的临界区访问机制,来达到这一目的,而在设计访问机制时需要有一定原则。

忙则等待

当临界区忙时,即是已经有进程进入到了临界区,其他进程必须在临界区外等待当前进程在临界区中完成运行。

空闲让进

当无进程处于临界区时,任何有权进程都可以进入临界区。

有限等待

进程进入临界区的请求应在有限时间内得到满足。简单来说就是假设一个进程A进入了临界区执行,此时进程B在临界区外等待,但是操作系统不能让进程B 长时间的等待,使其处于资源缺乏的饥饿状态。思考: 临界区的设置大些还小些好?答案:临界区的设置不能无根据的扩大,这样会使得其他需要进入该临界区的进程的等待时间变长,临界区的大小设置是根据不同进程的实际情况而定,总之在不影响进程执行得到正确结果的情况下,越小越好。

让权等待

e16972535fdd1f85692667be567feb96.png

等待进程放弃CPU(让其他的进程有机会得到CPU)
当一个进程到达临界区时,CPU会询问其是否可以进入临界区,当不能进入时,此时该进程进入等待状态,此时它应该放弃CPU,将控制权交还给操作系统,调度程序调度其他进程进行运行,而不是让CPU一直询问是否能够进入临界区。

03

 锁机制

基本原理

设置一个标志,来判断当前临界区是否可以进入

f43702e5ad1475cfa08f5570644891fb.png

其实这可以通俗的理解为:
临界区-->卫生间、锁标志-->卫生间门(不恰当的比喻 ^ _ ^)
当一个进程需要进入某个临界区时,首先检查该临界区的标志(卫生间门是否是开着的)是否为可用,是则进入,反之等待。进程进入到临界区后,将标志更改为不可用(进入卫生间要关门),退出临界区时将标志修改为可用(出卫生间要开门)。

上锁操作

Lock(S) {//上锁原语    test:if (S == 0 ) {        goto:test;//测试锁标志    } else {        S = 0;//上锁    }}

开锁操作

Unlock(S) {//开锁原语    S = 1;}

04

PV操作解决进程同步问题

同步机制的实质

- 运行条件不满足时,能够让进程阻塞
- 运行条件满足时,能够让进程立即继续

P-V操作应用与进程同步的基本思路

- 暂停当前进程:在关键操作前执行P操作---->必要时可暂停
- 继续进程:在关键操作之后执行V操作------>必要时唤醒合作进程
- 定义合理并且有意义的信号量,设置合适的初值

实例:公交车司机和售票员

时间回到2010的那个年代,想必大家都做过有售票员的公交车或者客车,这里以这个场景为例,来展示如何利用P-V操作实现进程间的同步

司机:起步、驾驶、停车

售票员:开门、售票、关门

同步要求:
- 只有在售票员将车门关好之后,司机才能够起步
- 只有司机停好车之后,售票员才能够打开车门
很容易就可以分析出:司机的关键操作是起步和停车;而售票员的关键操作是开门和关门。

关键操作的判断条件

  1. 该操作的执行需要一定的条件(在该操作之前添加P操作)

  2. 该操作执行完成与否影响到合作进程的某个操作(在该操作之后添加V操作)

ef1c223c3174b2faad1d178f27c6900e.png

假设司机进程先运行,首先执行P操作,判断门是否关好,初值为0,未关好,则司机进程阻塞,售票员进程继续执行。

9c8ddafdc2bae470fbf01758eb7096f4.png

售票员执行关门操作:然后执行V操作:s1= 0 并且唤醒司机进程

90ff788aed4a8ee6cb6766c55c97de4c.png

司机和售票员并发执行驾驶和售票操作,互不影响:

93e1fcc35a7a9d7574bf64c3293e600d.png

假设此时即将到站,售票员试图开门,会先执行P操作:判断车是否停好,此时S2 = 0,售票员进程会被阻塞,S2 -> -1;

f588729f4a4c3a7cdea66c774c07d3ef.png

司机进程继续,然后执行停车操作,停好车之后,执行V操作,使得S2 = 0 ;并唤醒售票员进程:

049a483c91f8d1cada830038bbf4f39b.png

至此,该司机和售票员的一个进程同步过程就顺利完成了。

334fa95de52f56e688c81ee65ab410df.png

然Coder

微信号 : huazai990728

CSDN:LengDanRan

9bcd984bbffa25f04c67d2f8fba6a4ff.gif

分享、在看与点赞

只要你点,我们就是胖友

9bcd984bbffa25f04c67d2f8fba6a4ff.gif
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值