(转)很有借鉴意义!读者写者问题--使用信号量的读者优先与写者优先程序分析

转自http://www.linuxso.com/linuxbiancheng/13098.html

千万要注意:readcount,writecount要设成共享变量(因为是进程),要不然可能会导致死锁

所谓谁谁优先的问题,我认为主要体现在以下两点中:

1.当低优先级进程(线程)获得临界区时,高优先级进程能很快从低优先级的进程中抢得访问权。

2.当高优先级的进程获得临界区访问权时,低优先级得等到高优先级全部访问完的空闲时间才能抢得访问权。

这两点中, 第一点一定得要,不然无法体现出优先的意思 。

第二点可以根据程序的需要决定。

程序摘自:《操作系统精髓与设计原理》

/* program readersandwriters*/
//读者优先,经过我修改了一点
int readcount = 0;
semaphore x = 1,z = 1, wsem = 1;
void reader()
{
	while(true){
		semWait(x);
		readcount ++ ;
		if(readcount == 1)
			semWait(wsem);
		semSignal(x);

		READUNIT();//读数据

		semWait(x);
		readcount --;
		if(readcount == 0)
			semSignal(wsem);
		semSignal(x);
	}
}
void writer()
{
	while(true){
		semWait(z);//自己加的,不过这样降低了写操作的效率,但满足了以上2点。去除z信号后,就只满足第1点,可以自己分析分析
		semWait(wsem);
		WRITEUNIT();//写数据
		semSignal(wsem);
		semSignal(z);
	}
}

程序中semWait 就是指信号量P 操作, semSignal 就是指V

首先明白一点 如果某一信号初始值为1 ,且在一个函数中是P,V操作是成对出现 ,那么这个信号量就是用来起互斥作用!

信号量x ,是用来保证readCount 自加自减操作和if条件语句操作的原子性。

来分析下为什么这个程序是读优先呢?

1.考虑下这种情况:如果读者已经获得临界区的访问权,那么当读者连续不断时(即中间间隔小),也就是说当一个进程读完前,另一个进程也进入到了临界区。 此时的话,任一时间在临界区中的写进程者会大于一 。 即使来了写进程,也只能有一个写者阻塞在wsem信号中,其余全阻塞在z信号中。。。直到某一时刻,无读者在临界区时,才有机会写临界区。

2.在考虑一种情况:写进程已经获得了临界区的访问权,且写进程也很密集。 此时读进程能不能优先得到访问权而不用等到写进程全部访问完呢?

答案是能。  写进程很多,那么一次又只能有一个写进程访问临界区。则其余的写进程都会在z信号中阻塞,排队且。 如果读进程也想访问了,读进程就会在wsem信号中阻塞排队即只有读进程会在wsem中阻塞排队。   注意:当此时的写进程一旦完成访问临界区WRITEUNIT . 下一句semSignal(wsem) , 好, 此时阻塞在wsem队列中的读进程就抢得到临界区的访问权。。

综上所述:在读者优先的程序中:写进程只有等待无读者访问临界区的时刻,才能得到访问权 ; 读进程在任意时候都可以得到访问权。

阻塞在wsem队列中最多只有一个写者 ,其余的写者阻塞在z信号中。  wsem队列中当然最多可能有有限个写者(因为写者能有很短的时候内得到访问权)

//写者优先

/*program readersandwriters*/
//写者优先
int readcount , writecount;
semaphore x = 1, y = 1, z = 1, wsem = 1 , rsem = 1;
void reader()
{
	while(true){
		semWait(z);//z信号用来保证阻塞在rsem信号中排队的读者至多只有一个。其余的阻塞在z上。
			semWait(rsem);
				semWait(x);//保证下面3句操作的原子性
					readcount ++;//在这里,当有写者出现时,由于rsem的阻塞,readcount的值不会大于1
					if(readcount == i)//i应该是1才对
						semWait(wsem);//为了让真正执行READUNIT()时没人打扰
				semSignal(x);
			semSignal(rsem);//写者抢占访问权的时机!
		semSignal(z);

		READUNIT();

		semWait(x);
			readcount --; //由于上面readcount只能为1,所以下面语句必然执行
			if(readcount == 0)
				semSignal(wsem);
		semSignal(x);
	}
}

void writer()
{
	while(true){
		semWait(y);
			writecount ++;
			if(writecount == 1)
				semWait(rsem);//第一个写者阻塞地方
		semSignal(y);

		semWait(wsem);//为了让真正执行WRITEUNIT()时没人打扰

			WRITEUNIT();
		semSignal(wsem);

		semWait(y);
			writecount --;
			if(writecount == 0)//最后一个写者才释放rsem,这时读者才有机会访问,读者也才有机会semWait(wsem)                                              ,否则在没机会semWait(wsem),写者当然可以继续
				semSignal(rsem);
		semSignal(y);
	}
}

同前面一样, y是用来保护写者中对writecount操作的原子性。

1.当读者获得了访问临界区的权利时,且读者进程访问的很密集时(即很多读者都需要访问),写者如何抢得访问权。

当读者获得访问权时即有一个进程正在执行READUINT操作时。和上一个读者优先程序中的写者差不多,如果没有写者,那么读者就能一个接一个到达临界区访问。但是因为READUINT操作前由于有z信号和rsem信号的互斥作用。使得读者一个只有一个通过这一段代码,其余的者阻塞在z信号中。进入临界区时是依次进入的(但出来不一定是先进先出) 。 一旦此时来了一个写者,他就会阻塞在rsem信号中。等会此时的读者刚一执行完semSignal(rsem)时,那么写者就得到rsem信号可以继续执行了。然后写者就只用等待读者中已经进入临界区的出来就能执行了。

2.当写者获得临界区的访问权时,读者只能等到临界区空闲时才能得到临界区访问权。

因为当写者获得临界区时,所有的读者都会阻塞在z信号和rsem信号中。   而只有最后一个写者访问完临界区时,才会semSignal(rsem), 使得阻塞在rsem中唯一的读者获得临界区访问权。

z信号的作用是 当读者获得权限时, 此时来的写者不用等待他前面所有的读者都访问完才访问 。  因为z信号使得在rsem信号队列中至多只有一个读者阻塞

转载注明出处

时间: 2024-08-30 11:32:12

(转)很有借鉴意义!读者写者问题--使用信号量的读者优先与写者优先程序分析的相关文章

《失控》对当下的互联网投资有哪些借鉴意义

<失控>由凯文·凯利成书于 1994 年,记述了他对当时科技.社会和经济最前沿的一次漫游,以及借此所窥得的未来图景.本文作者是一名投资人,他从投资人的角度解读了他对<失控>的理解,并探讨了<失控>对今天的互联网投资有哪些借鉴意义. 今天很高兴和大家一起分享<失控>这本书.作为一名投资人,我始终关注的是我们可以从<失控>中汲取什么智慧,以此来认识这个世界并指导我们日常的投资.例如,人工智能是未来重要的投资标的,什么特性的公司最具有成功的可能? 同时

我需要完全理解这部分代码才能确保它能够正常工作,如果由我来修复代码中的问题,我是不会这么写的,因此希望你也不要这么来写(转)

Jim Bird是一位经验丰富的软件开发经理.项目经理与CTO,专注于软件开发与维护.软件质量与安全等领域中疑难问题的解决.在过去的15年间,Jim曾管理过团队建设并主导过高性能的财务系统的建设.他的主要兴趣在于如何提升小团队的效率以构建真正的软件:高质量.安全.可靠.高性能及适应性强.近日,Jim撰写了一篇博文,谈到了代码审查的价值,如何进行代码审查,代码审查的过程以及在代码审查中需要注意的问题,希望能为大家平日的代码审查带来一些启示. 开始代码审查 从一开始,开发者就会互相帮助,如果测试中遇

写JQuery 插件 什么?你还不会写JQuery 插件

http://www.cnblogs.com/Leo_wl/p/3409083.html 前言 如今做web开发,jquery 几乎是必不可少的,就连vs神器在2010版本开始将Jquery 及ui 内置web项目里了.至于使用jquery好处这里就不再赘述了,用过的都知道.今天我们来讨论下jquery的插件机制,jquery有着成千上万的第三方插件,有时我们写好了一个独立的功能,也想将其与jquery结合起来,可以用jquery链式调用,这就要扩展jquery,写成插件形式了,如下面就是一个简

一步步写 CMOS 驱动模块 &lt;ELDD 学习笔记&gt; (最近更新,写到open release为止)

一步步写 CMOS 驱动模块 Let's implement a char driver to access the system CMOS. 首先仅仅是创建设备模块,最简单的,类似于前面hello world模块一样的东东,从最简单的框架慢慢搭 /************************************************************ code writer : EOF code date : 2014.08.15 code file : cmos_demo.c

代做Shell作业、代写代做Unix、Linux作业、代写国外shell作业

代做Shell作业.代写代做Unix.Linux作业.代写国外shell作业这个项目是为了创建一个文件同步器.1.1介绍许多计算机用户希望从不同的机器上访问他们的文件,最方便的方法是使用单一的文件系统,这个文件系统通过网络上的多台机器安装.机器在不同的网络时,系统共享的文件不能轻易被使用.举个例子,一个用户在两台机器(携带式和台式)上拥有相同的文件,当一个携带式机器上的文件被更改时,而它此时并没有接到网络中,那么它必须手动将新版本复制到系统中(这个系统只含有旧版本的文件),当文件分别在这两个系统

对Qt for Android的评价(很全面,基本已经没有问题了,网易战网客户端就是Qt quick写的),可以重用QT积累20年的RTL是好事,QML效率是HTML5的5倍

现在Qt不要光看跨平台了,Qt也有能力和原生应用进行较量的.可以直接去Qt官网查看他和那些厂商合作.关于和Java的比较,框架和Java进行比较似乎不且实际.如果是C++和Java比较,网上有很多文章,可自行翻阅,不要在知乎上看C++和Java比较,黑了C++,捧了Python和PHP.Java呢?晾一边了.在安卓上的话,现在问题可能很多,但是随着Qt的更新,大体解决得七七八八了.Qt on Android 对于原有Qt开发人员和爱好者是一个不错的选择,虽然在Qt可以完成大部分安卓的对应功能,可

一个很有借鉴价值的编程故事

转载:http://kb.cnblogs.com/page/510039/ 摘要:一周七天,每天学一点在线课程,哪怕一次只有半小时,只要坚持不懈,你就能感觉到自己今天做出的决定是正确的.请记住:只要有耐心,任何能干的人都能成为绝世coder,当然也包括你. 英文原文:A Cautionary Tale of Learning to Code 这是一个真实的故事,关于我自己的.一个理智的生命个体是怎么一步步走向疯狂? 我穿着西装,坐在办公室里,脑子里有一个模糊的创业想法.然后,我决定学习编程.我曾

一个很有借鉴价值的编程故事(转)

英文原文:A Cautionary Tale of Learning to Code 这是一个真实的故事,关于我自己的.一个理智的生命个体是怎么一步步走向疯狂? 我穿着西装,坐在办公室里,脑子里有一个模糊的创业想法.然后,我决定学习编程.我曾经无意中听到过几个人在那吹牛说自己怎么使用一种叫 Ruby 的语言轻松实现自动办公.我想“呵,Ruby”.我回到家,谷歌 Ruby.15 秒之后,我随机选择了一个 Ruby 教程,开始学习. 一周以后,我参加人生中的第一次黑客聚会.在场的每个人都在讨论什么

(原创)多系统间需要对接,我写了一个接口框架。实用性非常强,写出来大家交流。需要的可以直接搬过去用。(第1篇)

业务是这样:有个手机app,在ios或者android上开发的,他需要访问服务器数据.我在服务器上,做了一个接口,专门开放一些数据给app去用. 我写的接口优势:我写的这个接口,全部是面向对象结构,代码简单而非常好用,极易扩展.可读性很强,容错性高. 个人建议有需要的同学可以直接拿去用到项目中..我会一步步讲他的制作方法. 第1步,创建一个工程,在工程中,创建一个网站,以及一个业务操作类库.如下图: 上图是网站. 上图是类库 第2步,创建几个根类.cs文件.如上图,创建:Post.cs文件:用于