搜索
当前位置: 秒秒彩官网 > 读入原语 >

临界区的互斥

gecimao 发表于 2019-09-04 00:13 | 查看: | 回复:

  是共享的资源(如共享文件,共享变量,全局变量等)进行访问的一段程序代码。访问共享的内存是临界区和其他代码相区别的地方,当计算机中运行的多个进程都有执行临界区的代码的时候,这个时候就会出现对共享内存的竞争。如果多个临界区都是对共享内存进行读,则问题不大,不会出现竞争;当某个临界区想要修改共享内存时,这个时候问题就大了!如果进程A要修改某个共享变量,读取该变量进行修改后,正要往回写却被挂起,另外一个进程B执行的时候又读取了该共享变量。这个时候便发生了。进程B读取到的值是老的值,并不是更新之后的值。类似的情况还有很多,都会导致竞争条件,两个或多个进程读写某些共享数据时,最后的结果取决于进程运行的精确顺序。

  那么问题就来了,如何让各个临界区读写共享数据时不出现竞争条件呢?也就是,如何实现临界区的互斥呢?

  在单处理器系统中,发生竞争的原因很大一部分是因为在访问共享内存时,进行了进程切换,也就是执行临界区的进程被挂起了,然后其他的临界区又去访问了共享内存。一个简单粗暴的方法就是在执行临界区时直接屏蔽中断。屏蔽中断后,时钟中断也被屏蔽,而CPU只有在发生时钟中断时才能切换进程。访问共享内存时不能切换进程也就保持了访问共享内存的连续性,不能被其他进程打断,对共享内存的访问也就保持了一致性。其他进程想要访问就只能等着了(忙等)。

  但是这个方法并不好,将屏蔽中断的权利交给用户进程是很不安全的,如果用户进程进入临界区后不打开中断,则整个系统可能会因此而崩溃。而且对于多核处理器,并不能阻止其他CPU上运行的进程对共享变量的访问。

  很形象地来说,就是为共享内存加一把锁,当有进程的临界区想访问这个共享内存时要先试试能不能打开,如果能打开就可以访问,如果不能打开就一直等着,等到能打开为止(也就是忙等)。具体的实现方法:先创建一个共享变量(也就是锁,这把锁也需要共享才能让其他进程也能访问到。不过正是因为锁也是共享的,访问恭锁变量的代码也成了临界区,这又引入了新的问题),并初始化锁为0,代表可以访问共享内存,如果是1则代表有进程正在访问共享内存,要等到锁为0时才能访问(忙等)。

  锁变量的问题很明显,当不同进程测试锁的时候也是在执行临界区,那么又怎么保证访问锁变量时能互斥呢?

  严格轮转法其实是锁变量的一种。严格轮转法中有一个整型变量 turn 来记录轮到哪个进程进入临界区,初始值为0。实现严格轮转法的伪代码:

  严格轮转法同样有锁变量中的问题,谁来保证 turn 访问的互斥性呢?所以还是有可能两个进程都在访问同一块共享内存。除此之外,与锁变量相区别的是,严格轮转法的轮转的特性,从上面的代码也可以看出,要想访问共享内存,进程 0 和进程 1 需要交替地进行访问,但是如果这俩进程一个执行地飞快,而另一个又很慢呢?这个时候快的进程只能一直在while 那里循环,忙等,(用于忙等的锁也叫自旋锁)。对于执行速度差别较大的进程,不适合用轮转法。

  Peterson方法使用也使用轮转法中的 turn 变量,同时还用一个数组来记录谁想执行临界区。Peterson解法的代码如下:

  这里的interested数组就解决了上面提到的当turn 被多个进程访问时的问题。当多个进程同时写了turn,将其设置为自己的进程号(0 或 1),但只有后写入的进程号才有效,先被写入的turn被后写入的turn所覆盖。假设进程1 是后写入的,则turn 为 1,当两个进程都运行到 while 语句时,进程 01执行0 次循环并进入临界区,而进程1则循环直到进程 0 退出临界区为止。

  TSL指令成为 测试并加锁(Test and Lock),上述代码将内存字 LOCK 读到寄存器 RX 中,然后在该内存地址上存一个非零值。注意,读和写字操作是原子的(不可分割的)。执行 TSL 指令的CPU将锁住内存总线,以禁止其他CPU在本指令结束之前访问内存。锁住存储总线和屏蔽中断不一样,屏蔽处理器在多核处理器中不可行,但锁住总线后其他的处理器则不能访问内存了。使用TSL指令来实现互斥如下:

  TSL 指令将LOCK 原来的值复制到寄存器中并设置为1,随后这个原来的值与 0 比较,如果非零,则已经被加锁,重新测试;若为0则RET,调用者执行临界区。

  原语是不可中断的过程。sleep原语会使调用者进入休眠状态,被阻塞;wakeup原语会唤醒某个进程。slepp 和 wakeup 一般会作为系统调用。在使用slepp 和 wakeup时,一般会根据某个变量的值来调用slepp 和 wakeup实现互斥。如生产者-消费者问题:

  该方法的问题是对count的访问时竞争的,容易导致唤醒信号丢失。例如,当消费者发现缓冲区为空并读取到count为0,在sleep之前被挂起,之后生产者运行,生产一个item后发现count为1,认为消费者在睡眠,然后遍wankeup(consumer),给消费者发送唤醒信号,但是此时消费者并未睡眠,所以唤醒信号丢失。当消费者运行时,因为之前读取的count为0,于是sleep。随后生产者迟早会填满缓冲区,然后sleep。于是消费者和生产者都睡眠,没人去唤醒任何一个。

  信号量使用一个整型变量来累积唤醒次数,这个变量就叫做信号量,信号量的取值可以为0和正值。信号量中也使用了两个操作,down和up(也叫p和v)。对一信号量执行down操作,则是检查其值是否大于0,。若该值大于0,则将其值减1(即用掉一个保存的唤醒信号)并继续执行;若为0,则进程将睡眠,此时down并未结束。对一信号量执行up操作,将会对信号量增加1.如果一个或多个进程在这个信号量上睡眠,即有进程的down操作未完成,则唤醒其中一个睡眠的进程继续完成它的down操作。**注意,down和up操作的检查数值、修改变量以及可能发生的睡眠操作是不可分割的。**使用信号量解决生产者-消费者问题:

  看似信号量很好的解决了互斥的问题,但是考虑一个问题,若一下代码交换次序的话:

  则有可能生产者被阻塞,同时也会使消费者被阻塞。这样两个进程都会阻塞。注意,使用信号量时需要非常小心,注意操作的顺序!

  一个管程是由过程、条件变量及数据结构等组合成的一个集合,它们组成一个特殊的模块或软件包。进程可以在任何需要的时候调用管程中的过程,但它们不能在管程之外的声明的过程中访问管程中的数据结构。管程的一个重要特性是:任一时刻管程中只能有一个活跃进程。需要注意的是,管程是编程语言的组成部分,编译器知道它们的特殊性,因此可以采用与其他过程调用不同的方法来处理对管程的调用。管程中通常使用条件变量来使无法运行的进程阻塞,以及两个操作:wait和signal。

  在这个部分,我总是难以放下一个观点,就是觉得算法的设计故意设计的很蠢,下面会逐一说明。首先看算法一:单标志法。核心思想:设置一个公共整形变量turn,用于指示被允许进入临界区的进程编号。若turn=0...博文来自:Bings Blog

  转载自临界区,互斥量,信号量,事件的区别四种进程或线程同步互斥的控制方法临界区:通过对多线程的串行化来访问公共资源的一段代码,速度快,适合控制数据访问。互斥量:为协调共同对一个共享资源的单独访问而设计...博文来自:ShuJk的博客

  临界区和互斥锁的区别1、临界区只能用于对象在同一进程里线程间的互斥访问;互斥体可以用于对象进程间或线、临界区是非内核对象,只在用户态进行锁操作,速度快;互斥体是内核对象,在核心态进行...博文来自:boywgw的专栏

  1、临界区criticalsection临界区线程同步在Windows核心编程中被称为关键段线程同步,关键段是一小段代码,它在执行之前需要独占对一些资源的访问权。缺点:能且只能用在一个进程中的多线程同...博文来自:LingLee

  四种进程或线、临界区:通过对多线程的串行化来访问公共资源或一段代码,速度快,适合控制数据访问。 2、互斥量:为协调共同对一个共享资源的单独访问而设计的。 3、信号量:为控制一个具...

  ----------软件实现方法:        在进入区设置和检查一些标志来表明是否有进程在临界区中,如果已有进程在临界区,则在进入区通过循环检查进行等待,进程离开临界区后则在退出区修改     标...

  问:互斥量和临界区的区别答:互斥量和临界区具有相同的性质;一下两条是区别       1)临界区的作用范围仅限于本进程,其它进程无法获取该锁。       2)互斥量在系统中任何进程都是可见的,即一个...

  详细步骤,有界面提示,当多个线程访问一个独占性共享资源时,可以使用“临界区”对象。任一时刻只有一个线程可以拥有临界区对象,拥有临界区的线程可以访问被保护起来的资源或代码段,其他希望进入临界区的线程将被挂起等待,直到拥有临界区的线程放弃临界...

  用VC实现两个线程的同步,申请不当则可能会发会死锁.br此例就是如此

  1.是不是内核对象???rnrn2. 不删除会怎么样???rnrnrnrn

  1、临界区:通过对多线程的串行化来访问公共资源或一段代码,速度快,适合控制数据访问。2、互斥量:为协调共同对一个共享资源的单独访问而设计的。临界区(CriticalSection)保证在某一时刻只...

  四种进程或线、临界区:通过对多线程的串行化来访问公共资源或一段代码,速度快,适合控制数据访问。 2、互斥量:为协调共同对一个共享资源的单独访问而设计的。 3、信号量:为控制一个具...

  概念要点  同步可以解决诸如竞态条件、数据竞争、缓存变量的线程问题。同步是JVM的一个特性,在保证两个或者多个并发线程不会同时执行同一块临界区,临界区就必须以串行方式访问的一段代码块。  因为其他线程...

  所谓的临界区,就是并发进程中与共享的变量有关的程序代码段,而吧改断码变量代表的共享资源的称为u临界资源。 对于的临界区的管理的必须要满足一下的四个要求:1.不存在有关的额进程相对推进的速度,系统内多个...

  之前学习了临界区的使用,但是使用方式是极其不方便的,还使用了一个全局变量CRITICAL_SECTIONsection;调用函数还要访问变量,整个临界区代码散落在各地,本文使用封装来增加代码的可读性。...

  QT4 线程 临界区的使用 代码简洁 能说明QT下线程的使用 方法,代码有注释,易扩展

  有收发两个buffer,每个buffer各有一个读指针和写指针。rn有三个线程,一个收,一个发,另一个解析收到的内容,根据解析结果确定要发送的内容rn我使用临界区则程序一直无法收到东西,用互斥量就能正常运行。(代码写在相同的位置)rn请问有什么区别?我一直想不通为什么。

  因为涉及到多线程读写变量的问题,因此需要用临界区去确保不冲突。rn这里就存在一个问题rn主线.cpp和.hrnrn线程是定义在一个类里面,从tthread继承的,是threadunit.cpp和.hrnrn那么此时如果要用TRTLCriticalSection,那么这个临界区变量应该申明在什么地方呢??rn网上搜到的大多都是直接用线程函数,然后都在一个单元里面

  最近跟踪了一个程序的界面卡死问题,该卡死偶尔出现,在抓到一次dump后用windbg载入分析,打印出函数调用堆栈后,一眼可以看出是临界区死锁了。代码:0:000:x86kbChildEBPRe...

  假设使用临界区来控制线程对资源S的互斥访问,假设线程A已经锁定该临界区,此后线程B,C,D又先后请求访问资源S。我想问的是:当线程A释离开临界区的时候,系统将把临界区的使用权交给哪个项程呢,是按请求顺序交给B,还是这3个线程谁先获得cup控制权,谁就先进入临界区。如果是这样,那还有没有办法实现按照请求顺序来分配临界区!!!!

本文链接:http://k-mood.com/duruyuanyu/648.html
随机为您推荐歌词

联系我们 | 关于我们 | 网友投稿 | 版权声明 | 广告服务 | 站点统计 | 网站地图

版权声明:本站资源均来自互联网,如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

Copyright @ 2012-2013 织梦猫 版权所有  Powered by Dedecms 5.7
渝ICP备10013703号  

回顶部