《UNIX程序设计》哈理工版本 信号量读者写者问题

合集下载

操作系统——读者-写者问题的解决方法

操作系统——读者-写者问题的解决方法

操作系统——读者-写者问题的解决⽅法问题描述不允许Write进程和Read进程或其他Write进程同时访问⽂件,Read进程可以和其他Read进程同时访问。

分为三种类型。

读者优先要求:1.多个读者可以同时访问⽂件2.同⼀时间只允许⼀个写者访问⽂件3.读者和写者进程互斥解决⽅法:⽤⼀个readcounter记录是第⼏个读者在读,如果是第⼀个读者,则不能让写者写,需要⼀个锁。

因为readcounter是临界资源,也需要⼀个互斥量。

semaphore rc_mutex = 1, wmutex = 1;readcounter = 0;void writer{do{wait(wmutex);//writesignal(wmutex);}while(TRUE);}void reader{do{wait(rc_mutex);if(readcounter == 0) wait(wmutex);readcounter ++;signal(rc_mutex);// readwait(rc_mutex);readcounter --;if(!readcounter) signal(wmutex);signal(rc_mutex);}while(TRUE);}写者优先要求:1.读者写者互斥2.写者读者同时等待时,所有等待的写者优先,等所有写者结束后,读者才能读3.没有写者时,读者能同时读4.写者到来时,不会终⽌已经进⾏的读者操作解决⽅法:semaphore wc_mutex = 1, prior = 1; //写者计数器,优先信号量readcounter = 0, writercounter = 0;void writer{do{wait(wc_mutex); //申请更改wc的权限if(writercounter == 0) //如果是第⼀个写者,就申请优先权限wait(prior);writercounter ++;signal(wc_mutex);wait(wmutex);//writesignal(wmutex);wait(wc_mutex);writercounter --;if(!writercounter)signal(prior); //当最后⼀个写者操作完成后,释放优先级权限 signal(wc_mutex);}while(TRUE);}void reader{do{wait(prior); //先申请优先级权限,如果前⾯还有写者就等待wait(rc_mutex);if(readcounter == 0) wait(wmutex);readcounter ++;signal(rc_mutex);signal(prior); //释放优先级权限// readwait(rc_mutex);readcounter --;if(!readcounter) signal(wmutex);signal(rc_mutex);}while(TRUE);}读写均等semaphore prior = 1; //读者和写者都等待在⼀个队列上,实现读写均等readcounter = 0, writercounter = 0;void writer{do{wait(prior);wait(wmutex);//writesignal(wmutex);signal(prior);}while(TRUE);}void reader{do{wait(prior);wait(rc_mutex);if(readcounter == 0) wait(wmutex);readcounter ++;signal(rc_mutex);signal(prior);//readwait(rc_mutex);readcounter --;if(!readcounter) signal(wmutex);signal(rc_mutex);}while(TRUE);}有错误请指出!。

读者写者问题

读者写者问题

读者-写者问题一个著名的同步问题是读者-写者问题(Courtois 等人,1971),它为数据库访问建立了一个模型。

例如,设想一个飞机订票系统,其中有许多竞争的进程试图读写其中的数据。

多个进程同时读数据库是可以接受的,但如果一个进程正在更新(写)数据库,则所有的其他进程都不能访问该数据库,即使读操作也不行。

这里的问题是如何对读者和写者进行编程?图2-47给出了一种解法。

在该解法中,第一个读者对信号量db 执行down操作。

随后的读者只是递增一个计数器rc。

当读者离开时,它们递减这个计数器,而最后一个读者则对信号量执行up,这样就允许一个被阻塞的写者(如果存在的话)可以访问该数据库。

在该解法中,隐含着一个需要注解的条件。

假设一个读者正使用数据库,另一个读者来了。

同时有两个读者并不存在问题,第二个读者被允许进入。

如果有第三个和更多的读者来了也同样允许。

现在,假设一个写者到来。

由于写者的访问是排他的,不能允许写者进入数据库,只能被挂起。

只要还有一个读者在活动,就允许后续的读者进来。

这种策略的结果是,如果有一个稳定的读者流存在,那么这些读者将在到达后被允许进入。

而写者就始终被挂起,直到没有读者为止。

如果来了新的读者,比如,每2秒钟一个,而每个读者花费5秒钟完成其工作,那么写者就永远没有机会了。

为了避免这种情形,可以稍微改变一下程序的写法:在一个读者到达,且一个写者在等待时,读者在写者之后被挂起,而不是立即允许进入。

用这种方式,在一个写者到达时如果有正在工作的读者,那么该写者只要等待这个读者完成,而不必等候其后面到来的读者。

该解决方案的缺点是,并发度和效率较低。

Courtois等人给出了一个写者优先的解法。

如下:一个写者优先的一个案例。

读者-写者问题解答计算机操作系统实验报告指导资料

读者-写者问题解答计算机操作系统实验报告指导资料

2.读者—写者问题读者—写者问题(Readers-Writers problem)也是一个经典的并发程序设计问题,是经常出现的一种同步问题。

计算机系统中的数据(文件、记录)常被多个进程共享,但其中某些进程可能只要求读数据(称为读者Reader);另一些进程则要求修改数据(称为写者Writer)。

就共享数据而言,Reader和Writer是两组并发进程共享一组数据区,要求:(1)允许多个读者同时执行读操作;(2)不允许读者、写者同时操作;(3)不允许多个写者同时操作。

Reader和Writer的同步问题分为读者优先、弱写者优先(公平竞争)和强写者优先三种情况,它们的处理方式不同。

(1)读者优先。

对于读者优先,应满足下列条件:如果新读者到:①无读者、写者,新读者可以读;②有写者等待,但有其它读者正在读,则新读者也可以读;③有写者写,新读者等待。

如果新写者到:①无读者,新写者可以写;②有读者,新写者等待;③有其它写者,新写者等待。

单纯使用信号量不能解决读者与写者问题,必须引入计数器rc 对读进程计数;rc_mutex 是用于对计数器rc 操作的互斥信号量;write表示是否允许写的信号量;于是读者优先的程序设计如下:int rc=0; //用于记录当前的读者数量semaphore rc_mutex=1; //用于对共享变量rc 操作的互斥信号量semaphore write=1; //用于保证读者和写者互斥地访问的信号量void reader() /*读者进程*/do{P(rc_mutex); //开始对rc共享变量进行互斥访问rc ++; //来了一个读进程,读进程数加1if (rc==1) P(write);//如是第一个读进程,判断是否有写进程在临界区,//若有,读进程等待,若无,阻塞写进程V(rc_mutex); //结束对rc共享变量的互斥访问读文件;P(rc_mutex); //开始对rc共享变量的互斥访问r c--; //一个读进程读完,读进程数减1if (rc == 0) V(write);//最后一个离开临界区的读进程需要判断是否有写进程//需要进入临界区,若有,唤醒一个写进程进临界区V(rc_mutex); //结束对rc共享变量的互斥访问} while(1)void writer() /*写者进程*/do{P(write); //无读进程,进入写进程;若有读进程,写进程等待写文件;V(write); //写进程完成;判断是否有读进程需要进入临界区,//若有,唤醒一个读进程进临界区} while(1)读者优先的设计思想是读进程只要看到有其它读进程正在读,就可以继续进行读;写进程必须等待所有读进程都不读时才能写,即使写进程可能比一些读进程更早提出申请。

OS:读者写者问题(写者优先+LINUX+多线程+互斥量+代码)

OS:读者写者问题(写者优先+LINUX+多线程+互斥量+代码)

OS:读者写者问题(写者优先+LINUX+多线程+互斥量+代码)⼀. 引⼦最近想⾃⼰写个简单的 WEB SERVER ,为了先练练⼿,熟悉下在LINUX系统使⽤基本的进程、线程、互斥等,就拿以前学过的 OS 问题开开⼑啦。

记得当年学读者写者问题,尤其是写者优先的时候,那是真⼼纠结啊。

刚才还觉得理解了,过⼀会⼉⼜糊涂了。

现在重新再看,还是容易纠结。

没办法,⽤得少。

我把读者优先和写者优先都实现了⼀下。

选择性重看了⼩部分《unix⾼程》使⽤了多线程+互斥量实现。

⼆. 互斥量与信号量互斥量如其名,同⼀时间只能被⼀个线程占有,实现线程间对某种数据结构的互斥访问。

试图对⼀个已经加锁的互斥量加锁,会导致线程阻塞。

允许多个线程对同⼀个互斥量加锁。

当对互斥量解锁时,阻塞在该互斥量上的线程会被唤醒,它们竞争对该互斥量加锁,加锁成功的线程将停⽌阻塞,剩余的加锁失败于是继续阻塞。

注意到,谁将竞争成功是⽆法预料的,这⼀点就类似于弱信号量。

(强信号量把阻塞在信号量上的进程按时间排队,先进先出)互斥量区别于信号量的地⽅在于,互斥量只有两种状态,锁定和⾮锁定。

它不像信号量那样可以赋值,甚⾄可以是负值。

共性⽅⾯,我所体会到的就⼀句话,都是⽤来实现互斥的。

⾄于其它区别或联系,⽤不上,不作研究。

三. 读者优先只要有⼀个读者正在读,那么后续的读者都能⽴即读,不管有多少写者在等待。

可能导致写者饥饿。

1. 读者1) 写者写时,不可读2) 有别的读者正在读,可读2. 写者1) 有读者正在读,不可写2) 有写者正在写,不可写3) ⽆读者正在读,⽆写者正在写,可写四. 写者优先当新的写者希望写时,不允许该写者后续的读者访问数据区,但必须保证之前的读者读完。

1. 读者特点1) 有写者正在写或者等待写,须等到没有写者才能读2) 没有写者,可以读2. 写者特点1) 写者与写者互斥。

当其它写者正在写时,其它写者不能写。

2) 写者与读者互斥。

之前只有读者在读,当写者出现时,必须等到之前的读者都读完才能写。

读者写者问题实验报告

读者写者问题实验报告

北京电子科技学院(BESTI)实验报告课程:操作系统班级:0921 姓名:学号:成绩:指导教师:徐小青实验日期:2011.11.22 实验密级:/ 预习程度:代码实验时间:12:50-15:20 仪器组次:A04 必修/选修:必修实验序号:(一)实验名称:用信号量来实现读者-写者问题实验目的与要求:理解进程(或线程)及信号量的概念实验仪器:一、实验目的:理解进程(或线程)及信号量的概念二、实验内容:1、定义一个数据缓存buffer及用于实现同步互斥的信号量。

2、定义一个读者函数:●当有写者在占用buffer时,读者应该等待,直到写者不再使用该buffer。

●当有其他读者在占用buffer时,读者可对buffer进行读取操作。

●当buffer中有数据时,则从其中读取一个数据,并显示然后退出。

●当buffer中没有数据时,应等待,直到buffer中有数据可读。

3、定义一个写者函数●当有读者在占用buffer时,写者应该等待,直到所有的读者都退出为止。

●当有其他写者占用buffer时,该写者应该等待,直到占用buffer的写者退出为止。

●当buffer有空闲时,写者应该在buffer中写入一个数据并退出。

●当buffer满时,写者应该等待,直到buffer有空闲为止。

4、定义主函数,在其中可以任意创建读者与写者。

可根据用户输入创建读者或写者进程(线程)。

三、实验当堂完成内容:1,将设计好的思路以代码形式呈现,并调通。

2,将数据改变,看结果是否符合预期设想3,与同学交流,将代码完善。

四、设计思想:读进程:read(){P(Sr); 申请区域P(Scot); 锁定读者计数器first = first+1;if(first ==1)P(Sdoc);V(Scnt); 解锁读者计数器开始读;P(Scnt); 锁定读者计数器V(Sdoc);V(Scnt);V(Sr);}写进程:write(){P(sdoc);开始写;V(sdoc);}主函数设计思想:五、代码及具体解释:#include <stdlib.h>#include <windows.h>#include <stdio.h>#define P(S) WaitForSingleObject(S, INFINITE)// 这是Windows 下多线程工作的P 操作#define V(S) ReleaseSemaphore(S, 1, NULL)// 这是Windows 下多线程工作的V 操作const int RN = 5 ; // 所有读者总数(可以改变)const int WN = 3; // 所有写者总数(可以改变)HANDLE Sdoc; // 文档信号量——互斥量(临界区的信号量题目要求是1)HANDLE Sr; // 读者信号量——广义信号量(一次最多有多少个读者在读)HANDLE Scnt; // 保护g_cntReader 的互斥量(目前有多少读者正在读)int g_cntReader = 0; // 读者个数计数器// funcname : JustWait ( )// note: 显示一些信息,让后等待// ret val : void//// + Parameter :// [ int ] - nReader 读者(写者)编号,读者>0,写者<0// [ int ] - min 操作等待的最短时间// [ int ] - max 操作等待得最长时间,实际等待的时间介于两者之间// [ LPCSTR ] - info 要显示的信息void JustWait(int nReader, int min, int max, LPCSTR info);DWORD WINAPI Reader(LPVOID lpPara);DWORD WINAPI Writer(LPVOID lpPara);// 这是主函数void main(){Sdoc = CreateSemaphore(NULL, 1, 1, "Document");// 创建信号量初值,最大信号量值Sr = CreateSemaphore(NULL, 3, 3, "ReaderNumber"); // 一次最多允许3 个Scnt = CreateSemaphore(NULL, 1, 1, "ReaderCounterProtect");// 他也是一个互斥信号量,初值为 1HANDLE threads[RN+WN];for (int i=0; i<RN; i++) //不断创建读者线程threads[i] = CreateThread(0, 0, Reader, 0, 0, 0);for (int j=0; j<WN; j++)threads[j+RN] = CreateThread(0, 0, Writer, 0, 0, 0);WaitForMultipleObjects(RN+WN, threads, TRUE, INFINITE);}// 读者线程DWORD WINAPI Reader(LPVOID lpPara){// 注意是静态变量,可以使每来一个读者增加一static int reader_num = 1;int i = reader_num ++;int x=0;while (x<=5){JustWait(i, 1, 2, "我想读"); //1s的时候来,给2s的时间去读P(Sr); // 读者未满P(Scnt); // 锁定读者计数器printf("还有%d 个读者在读, 读者%d进入\n", g_cntReader, i);g_cntReader ++;if (g_cntReader == 1) // 如果是第一个读者{JustWait(i, 1, 2, "我是第一个!");P(Sdoc); // 锁定文档printf("读者%d说:有人在读,不可写文件\n", i);JustWait(i, 1, 2, "我可以读文件了!");V(Scnt); // 解锁读者计数器释放JustWait(i, 2, 5, "我在读");// 读ing…………JustWait(i, 1, 2, "我将要离开!");P(Scnt); // 锁定读者计数器g_cntReader --;if (g_cntReader == 0) // 如果是最后一个{JustWait(i, 1, 2, "我是最后一个!");printf("读者%d说:可以对文件操作了!~~~\n", i);V(Sdoc);// 解锁文档}printf("还有%d个读者在, 读者%d离开\n", g_cntReader, i);V(Scnt);// 解锁读者计数器V(Sr); // 离开JustWait(i, 5, 3, "结束");x++;printf("%d\n",x);}return 0;}DWORD WINAPI Writer(LPVOID lpPara){// 注意是静态变量,可以使每来一个写者减去一,注意初值是负值static int g_cnt = -1;int j = g_cnt --;while (1){JustWait(j, 2, 4, "我想写");// 锁定文档P(Sdoc);printf("\t写者%d说:文件正在修改不可操作\n", -j);JustWait(j, 4, 3, "写···"); // 写ing……JustWait(j, 1, 2, "写完了,离开");printf("写者%d说:可以对文件操作了\n", -j);V(Sdoc);// 解锁文档JustWait(j, 8, 4, "休息了");}return 0;}void JustWait(int nReader, int min, int max, LPCSTR info)//min为读者到来时间,max为读者离开时间{const int BASETIME = 1000;// 等待时间的基本量,以毫秒表示int wait_time = 0;// 实际等待得时间if (max==min) // 判断是为了避免%0错误,注意取随机值wait_time = min*BASETIME;//处理时间为0;elsechar s_out[128];// 最终显示的信息缓冲if (nReader > 0)// 读者大于0,写者小于0sprintf(s_out, "读者%d说: %s\n", nReader, info);elsesprintf(s_out, "\t写者%d说: %s\n", -nReader, info);printf(s_out);// 打印Sleep(wait_time);// 然后等待}//其设计思想是:读者在读,来了写着,创建写着线程,利用时间片区分他们。

读者写者问题

读者写者问题
2)读-写互斥,即不能同时有一个读者在读,同时却有一个写者在写
3)读读允许,即可以有2个以上的读者同时读
将所有的读者与所有的写者分别放进两个等待队列中,当读允许时就让读者队列释放一个或多个读者,当写允许时,释放第一个写者操作。读者写者问题的定义如下:有一个许多进程共享的数据区,这个数据区可以就是一个文件或者主存的一块空间;有一些只读取这个数据区的进程(Reader)与一些只往数据区写数据的进程(Writer),此外还需要满足以下条件:1)任意多个读进程可以同时读这个文件;2)一次只有一个写进程可以往文件中写;3)如果一个写进程正在进行操作,禁止任何读进程度文件。我们需要分两种情况实现该问题:
一设计概述
所谓读者写者问题,就是指保证一个writer进程必须与其她进程互斥地访问共享对象的同步问题。
读者写者问题可以这样的描述,有一群写者与一群读者,写者在写同一本书,读者也在读这本书,多个读者可以同时读这本书,但就是,只能有一个写者在写书,并且,读者必写者优先,也就就是说,读者与写者同时提出请求时,读者优先。当读者提出请求时需要有一个互斥操作,另外,需要有一个信号量S来当前就是否可操作。
信号量机制就是支持多道程序的并发操作系统设计中解决资源共享时进程间的同步与互斥的重要机制,而读者写者问题则就是这一机制的一个经典范例。
与记录型信号量解决读者—写者问题不同,信号量机制它增加了一个限制,即最多允许RN个读者同时读。为此,又引入了一个信号量L,并赋予初值为RN,通过执行wait(L,1,1)操作,来控制读者的数目,每当有一个读者进入时,就要执行wait(L,1,1)操作,使L的值减1。当有RN个读者进入读后,L便减为0,第RN+1个读者要进入读时,必然会因wait(L,1,1)操作失败而堵塞。对利用信号量来解决读者—写者问题的描述如下:

读者-写者问题解答

2.读者—写者问题读者—写者问题(Readers-Writers problem)也是一个经典的并发程序设计问题,是经常出现的一种同步问题。

计算机系统中的数据(文件、记录)常被多个进程共享,但其中某些进程可能只要求读数据(称为读者Reader);另一些进程则要求修改数据(称为写者Writer)。

就共享数据而言,Reader和Writer是两组并发进程共享一组数据区,要求:(1)允许多个读者同时执行读操作;(2)不允许读者、写者同时操作;(3)不允许多个写者同时操作。

Reader和Writer的同步问题分为读者优先、弱写者优先(公平竞争)和强写者优先三种情况,它们的处理方式不同。

(1)读者优先。

对于读者优先,应满足下列条件:如果新读者到:①无读者、写者,新读者可以读;②有写者等待,但有其它读者正在读,则新读者也可以读;③有写者写,新读者等待。

如果新写者到:①无读者,新写者可以写;②有读者,新写者等待;③有其它写者,新写者等待。

单纯使用信号量不能解决读者与写者问题,必须引入计数器rc 对读进程计数;rc_mutex 是用于对计数器rc 操作的互斥信号量;write表示是否允许写的信号量;于是读者优先的程序设计如下:int rc=0; //用于记录当前的读者数量semaphore rc_mutex=1; //用于对共享变量rc 操作的互斥信号量semaphore write=1; //用于保证读者和写者互斥地访问的信号量void reader() /*读者进程*/do{P(rc_mutex); //开始对rc共享变量进行互斥访问rc ++; //来了一个读进程,读进程数加1if (rc==1) P(write);//如是第一个读进程,判断是否有写进程在临界区,//若有,读进程等待,若无,阻塞写进程V(rc_mutex); //结束对rc共享变量的互斥访问读文件;P(rc_mutex); //开始对rc共享变量的互斥访问r c--; //一个读进程读完,读进程数减1if (rc == 0) V(write);//最后一个离开临界区的读进程需要判断是否有写进程//需要进入临界区,若有,唤醒一个写进程进临界区V(rc_mutex); //结束对rc共享变量的互斥访问} while(1)void writer() /*写者进程*/do{P(write); //无读进程,进入写进程;若有读进程,写进程等待写文件;V(write); //写进程完成;判断是否有读进程需要进入临界区,//若有,唤醒一个读进程进临界区} while(1)读者优先的设计思想是读进程只要看到有其它读进程正在读,就可以继续进行读;写进程必须等待所有读进程都不读时才能写,即使写进程可能比一些读进程更早提出申请。

操作系统读者写者问题报告

操作系统读者写者问题报告
读者写者问题是一种典型的操作系统同步问题,其描述如下:有多个读者和写者同时访问共享资源,读者可以同时访问共享资源,但写者必须独占式的访问共享资源,即任何时刻只能有一个写者访问共享资源,且在写者访问共享资源的期间,任何读者都不得访问共享资源。

此外,读者在访问共享资源时不会修改共享资源,而写者则会对共享资源进行修改。

如何实现读者写者问题呢?简单来说,可以使用信号量机制来解决这个问题。

具体来说,可以使用两个信号量RdMutex和WrMutex,RdMutex用于锁定读者,在读者访问共享资源时,需要申请RdMutex信号量,如果有写者在访问共享资源,则RdMutex会阻止读者访问共享资源;而当最后一个读者结束访问共享资源时,需要释放RdMutex信号量,以便让其他等待的读者访问共享资源。

类似地,WrMutex用于锁定写者,在写者访问共享资源时,需要申请WrMutex信号量,如果有其他读者或者写者在访问共享资源,则WrMutex会阻止写者访问共享
资源;而当写者访问共享资源结束时,需要释放WrMutex信号量,以便让其他等待的写者访问共享资源。

除了信号量机制之外,还可以使用其他同步机制来解决读者写者问题,比如互斥量、条件变量等。

同时,操作系统还可以采用优化策略,比如写优先、读写优先等,来提高读写效率。

总之,读者写者问题是操作系统同步问题中的一个经典问题,其实现方式需要考虑多方面的因素,包括并发访问、同步机制、优化策略等,需要经过深入思考和有效实践才能得到较好的解决方案。

读者写者问题实验报告

读者写者问题实验报告引言读者写者问题是计算机科学中经典的同步问题之一,它涉及多线程编程中的资源竞争与同步机制。

通过对读者写者问题的研究,我们可以深入理解线程同步的重要性,并掌握解决并发编程中可能出现的竞争条件和死锁等问题的方法。

在本实验中,我们将设计并实现一个简单的读者写者问题的解决方案,并通过模拟多个读者和写者的并发访问来验证方案的正确性和效果。

问题描述读者写者问题可描述为:有一共享资源(如文件、数据库等),读者可同时访问共享资源进行读取操作,但写者在进行写入操作时,不可同时被其他任何读者或写者访问。

读者和写者的并发访问需要由线程同步机制来保证共享资源的一致性和完整性。

实验设计与实现为了解决读者写者问题,我们需要考虑以下几个关键点:1. 共享资源的访问控制我们可以使用互斥量(Mutex)来实现对共享资源的访问控制。

当一个线程访问共享资源时,它需要先获得互斥量的锁,如果锁已被其他线程占用,则线程进入等待状态,直到锁可用。

一旦线程完成对共享资源的访问,它将释放锁,以便其他线程继续访问。

2. 读者与写者的优先级在读者写者问题中,我们往往需要设定某个优先级规则,以确定读者和写者之间的调度顺序。

一种常见的策略是给予写者优先级,即当一个写者在等待访问共享资源时,其他读者都必须等待。

这样做是为了避免写者长时间等待,以免造成饥饿问题。

3. 记录读者和写者的数量为了控制读者和写者的并发访问,我们需要记录当前同时访问共享资源的读者和写者的数量。

我们可以使用整数变量来记录读者和写者的数量,并通过信号量来保证对这些计数变量的互斥访问。

4. 同步机制的设计在实现读者写者问题的解决方案时,我们需要考虑如何合理地使用互斥量和信号量,并结合优先级规则来实现读者和写者的同步。

这需要通过仔细的设计和调试来确保解决方案的正确性。

实验结果与分析我们基于上述设计实现了一个读者写者问题的解决方案,并进行了多次仿真实验。

实验环境•操作系统:Windows 10•编程语言:C++•编译器:GCC实验步骤1.编写读者和写者线程的代码,其中涉及到对共享资源的读取和写入操作,以及对计数变量和互斥量的访问操作。

“读者-写者”算法的讨论和改进

R ADE E R-1
I ADE 0 THE V W Rr F RE R= N ( - ) 写者 :
PW R ) ( T
修 改 信 息
V( R ) W T
11 利 用 信 号 量 解 决进 程 间 的制 约 关 系 . 多 道程 序 设 计 环 境 下 , 统 中 同 时执 行 多个 作 业 进 程 , 些 进 程 系 这 同时 共 享和 竞争 系统 中的 资 源 , 因此 必 然存 在 一 定 的制 约 关 系 。 程 进
修 改 信 息
V( R ) W T
3 读 者 一 者 算 法 的 改 进— — 写 者 优 先 写
在 算 法 中 , 一 种 极 端 情 况 , 有 一 个 读 者 进 程 在 读 , 使 写 者 有 即 而 读 一 写 互 斥 , 有 读 者 在 对数 据 进 行 访 问 时 , 何 写 者 不 能 对 其 操 进程 被 阻 塞 时 , 仍 然 有 读 者 不 断地 请 求 读 , 么 写 者 有 可 能 因读 者 即 任 却 那
这样 的解 法 看 起来 已经 没 有 问题 了, 因 为 它做 到 了第 一个 读 者
进去 了 , 其他 读 者 也 能 进 , 写者 不 能 进 。 是 又 出 现 了新 的 问 题 , 而 但 那
就是 如 果 是 写 者 先 进去 了 ,第 一 个 读 者 不 能进 ,而 其他 读 者 却 能 进
对这 些 数据 进行 访 问。
2 读 者一 写者 算 法 讨 论
当现 有读 者 完 成 之 后 ,就 让 写者 优 先 运 行 。 为 此添 加 一 个整 型 变 量 W RT C N , 录 写者 的数 目, W RT C IE OU T记 当 IE OU T = N 0时 才 可 以释 为 了实现 对 全局 变 量 W RT C N IE OU T的 互 斥访 问, 设置 了一个 互
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

哈尔滨理工大学
计算机科学与技术学院网络工程系
《UNIX程序设计》课程设计报告
题目:利用信号量机制解决读者写者问题
班级:
学号:
姓名:
成绩:
2011年月日
目录
一课程设计目的及意义 (1)
二课程设计内容 (1)
三总体设计 (1)
四详细设计 (2)
五系统实现 (3)
六总结 (5)
七源代码 (6)
一、课程设计目的及意义
l.用信号量来实现读者写者问题。

2.理解和运用信号量、PV原语、进程间的同步互斥关系等基本知识。

3.通过研究Linux的线程机制和信号量实现读者写者
(Reader-Writer)问题并发控制。

二、课程设计内容
在windows或者linux环境下编写一个控制台应用程序,本次课程设计在操作系统:Linux下,使用的编程语言为C语言。

该程序运行时能创建N个线程,其中既有读者线程又有写者线程,它们按照事先设计好的测试数据进行读写操作。

用信号量和PV操作实现读者/写者问题。

三、总体设计
读者/写者问题的描述如下:
有一个被许多进程共享的数据区,这个数据区可以是一个文件,或者主存的一块空间,甚至可以是一组处理器寄存器。

有一些只读取这个数据区的进程(reader)和一些只往数据区中写数据的进程(writer)。

以下假设共享数据区是文件。

这些读者和写者对数据区的操作必须满足以下条件:读—读允许;读—写互斥;写—写互斥。

这些条件具体来说就是:
(2)一次只允许一个写进程往文件中写;
(3)如果一个写进程正在往文件中写,禁止任何读进程或写进程访问文件;
(4)写进程执行写操作前,应让已有的写者或读者全部退出。

这说明当有读者在读文件时不允许写者写文件。

四、详细设计
读者-写者的读写限制
1)写-写互斥,即不能有两个写者同时进行写操作
2)读-写互斥,即不能同时有一个读者在读,同时却有一个写者在写
3)读读允许,即可以有2个以上的读者同时读
将所有的读者和所有的写者分别放进两个等待队列中,当读允许时就让读者队列释放一个或多个读者,当写允许时,释放第一个写者操作。

读者写者问题的定义如下:有一个许多进程共享的数据区,这个数据区可以是一个文件或者主存的一块空间;有一些只读取这个数据区的进程(Reader)和一些只往数据区写数据的进程(Writer),此外还需要满足以下条件:
(2)一次只允许一个写进程往文件中写;
(3)如果一个写进程正在往文件中写,禁止任何读进程或写进程访问文件;
(4)写进程执行写操作前,应让已有的写者或读者全部退出。

这说明当有读者在读文件时不允许写者写文件。

程序由二部分组成:
1.读者模块:包括系统调用接口,读者活动描述主程序。

系统接口主要功能是读取内容并且使用共享锁
2.写者模块:包括系统调用接口,写者活动描述主程序,写入内容并且使用互斥锁。

读者-写者活动程序根据临界资源的共享,互斥原则编制。

初始化系统环境
建立信号量
启动信号量的PV原语
读取或写入数据
提示当前读取或写入情况
五、系统实现
1.多个进程同时读取
2.多个进程读取,写进程不能执行
3.一个写进程,其他进程不能写也不能读
六、总结
这一次课程设计,让我体会很深刻。

读者-写者问题经典的线程同步问题的一个模型。

经过读者写者问题的编写,我对同步机构应用有了深入的了解。

懂得了运用信号量实现进程间的互斥。

实现了不让共享资源同时修改。

用信号量上的原语操作使临界段问题的解决比较简单明了了。

读者写者问题的编写,花的时间很多,也学到很多东西。

了解支持多道程序的并发操作系统设计中解决资源共享时进程间的同步与互斥的信号量机制。

几天的试验,虽然难度有点大,但只要自己花时间去学习,还是会攻克困难的。

总之,每一次课程设计不仅是我们学习的好机会,而且是我们锻炼实际动手能力的平台,虽然有难度的东西总会让人很抵触,比如在
课设过程中有很多郁闷的时候,一个小小的错误一不小心就花去了自
己一上午的时间,所以在这个过程中能够磨练人的意志与耐心,最后感谢老师的指导与监督。

附录A:代码
#include<sys/sem.h>
#include<sys/types.h>
#include<sys/ipc.h>
#include<stdio.h>
#include<sys/stat.h>
int main()
{
FILE *fp;
int semid;
int choose;
char ch;
struct sembuf sb[4];
unsigned short array[]={0,0};
semid=semget(0x1234,2,0666|IPC_CREAT);
semctl(semid,0,SETALL,array);
sb[0].sem_num=0;
sb[0].sem_op=1;
sb[1].sem_num=0;
sb[1].sem_op=-1;
sb[2].sem_num=1;
sb[2].sem_op=1;
sb[3].sem_num=1;
sb[3].sem_op=-1;
void show()
{
printf("当前的读者数为%d\n",semctl(semid,0,GETV AL));
printf("当前的写者数为%d\n",semctl(semid,1,GETV AL));
}
void reader()
{
if(semctl(semid,1,GETV AL)==0)
{
semop(semid,&sb[0],1);
printf("添加一个读者\n");
show();
sleep(50);
semop(semid,&sb[1],1);
printf("减少一个读者\n");
}
else
{
show();
printf("写者数不为0,不能读!\n");
}
}
void writer()
{
if(semctl(semid,0,GETV AL)==0 & semctl(semid,1,GETV AL)==0) {
semop(semid,&sb[2],1);
printf("添加一个写者\n");
show();
if((fp=fopen("/root/writerfile.txt","w"))==NULL)
{
printf("cannot open file \n");
exit(0);
}
printf("输入内容:");
ch=getchar();
while(ch!='#')
{
fputc(ch,fp);
putchar(ch);
ch=getchar();
}
putchar(10);
fclose(fp);
sleep(1);
semop(semid,&sb[3],1);
printf("写者写入结束\n");
}
else
{
show();
printf("读者或写者数不为0,不能写!\n");
}
}
int flag=1;
do{
printf("\n****************利用信号量机制解决读者写者问题***************\n");
printf("****************主菜单***************\n");
printf(" * 1.查看读者、写者人数\n");
printf(" * 2.增加一位读者\n");
printf(" * 3.增加一位写者('#'结束)\n");
printf(" * 4.退出程序\n");
printf("*************************************\n");
printf("请输入相应数字:");
scanf("%d",&choose);
printf("*************************************\n");
switch(choose){
case 1:show();break;
case 2:reader();break;
case 3:writer();break;
case 4:flag=0;printf("程序已退出\n");break;
default:printf("输入错误,请从新输入\n");
}
}while(flag);
}。

相关文档
最新文档