操作系统读者写者实验报告
操作系统实验报告(读者写着问题,时间片轮转算法,内存的分配,进程的调度)
电子科技大学计算机学院实验中心小心计算机专业类课程实验报告课程名称:操作系统学 院:软件学院专 业:软件工程学生姓名:李 希学 号:2010231020018指导教师:丁老师日 期: 2012年5月5日电子科技大学实验报告实验一一、实验名称:进程管理二、实验学时:4三、实验内容和目的:实验内容:(1)进程的创建写一段源程序,创建两个进程,当此程序运行时,在系统中有一个父进程和两个子进程活动。
让每一个进程在屏幕上显示字符。
观察纪录屏幕上的显示结果,然后分析原因。
(2)进程的控制修改编写的程序,将每个进程输出一个字符改为每个进程输出一句话,在观察程序执行时屏幕出现的现象,并分析原因。
实验目的:(1)加深对进程概念的理解,明确进程和程序的区别。
(2)进一步认识并发执行的实质。
(3)分析进程竞争资源现象,学习解决进程互斥的方法。
四、实验原理:利用fork函数来创建子进程,并返回子进程的ID号。
利用lockf函数来实现信号量对进程的资源竞争的调度,和互斥的方法。
五、实验器材(设备、元器件):一台装有VS2010的电脑,操作系统为WIN7.六、实验步骤:(1)先写好2个子进程程序,并且让2个子程序在屏幕上分别打印出A,B(2)父进程创建2个子进程,并在屏幕上打印出C。
(3)观察进程竞争资源的现象。
七、实验数据及结果分析:电子科技大学计算机学院实验中心子进程A的代码:#include<iostream>#include<windows.h>using namespace std;int main(){cout<<"I'm Process A/n"<<endl;return 0;}子进程B的代码:#include<iostream>using namespace std;int main(){cout<<"I'm Process B"<<endl;;return 0;}父进程C的代码://#include "stdafx.h"#include<windows.h>#include<iostream>using namespace std;void print_error(){DWORD nErrorNo = GetLastError ( );LPSTR lpBuffer;FormatMessage ( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_IGNORE_INSERTS |FORMAT_MESSAGE_FROM_SYSTEM,NULL,nErrorNo,LANG_NEUTRAL,(LPTSTR) & lpBuffer,0 ,NULL );if (lpBuffer == NULL){lpBuffer = "Sorry, cannot find this error info. ";}printf("%s (%d).\n", lpBuffer, nErrorNo);}int fork(const char* pszApplication,HANDLE& hProcess){STARTUPINFO si={sizeof(si)};PROCESS_INFORMATION pi;if(!CreateProcess(pszApplication,NULL,NULL,NULL,FALSE,0,NULL,NULL,&si,&pi)) return -1;else{hProcess=pi.hProcess;return pi.dwProcessId;}}void lockf(HANDLE hObj){DWORD state = WaitForSingleObject(hObj,INFINITE);switch (state){case WAIT_OBJECT_0:printf("\nProcess exit.\n");break;case WAIT_TIMEOUT:printf("\nTime out.\n");break;case WAIT_FAILED:printf("\nWait Failed.\n");print_error();break;}}int main(int argc, char* argv[]){HANDLE hProcess1,hProcess2;int child1=fork("C:\\操¨´作Á¡Â系¦Ì统ª3实º¦Ì验¨¦\\ProcessA\\Debug\\ProcessA.exe",hProcess1);if(-1==child1){cout << "fork error!\n";return -1;}lockf(hProcess1);电子科技大学计算机学院实验中心int child2=fork("C:\\操¨´作Á¡Â系¦Ì统ª3实º¦Ì验¨¦\\ProcessB\\Debug\\ProcessB.exe",hProcess2);if(-1==child2){cout << "fork error!\n";return -1;}cout<<"This is Process C\n";lockf(hProcess2);return 0;}程序运行的结果:八、实验结论、心得体会和改进建议:实验结论:成功的通过了父进程C来创建了2个子进程A,B,并成功的对子进程进行了调度与管理。
读者写者实验报告
读者写者实验报告
读者写者问题是指一个共享固定大小缓冲区的进程间通信问题,其中固定大小的缓冲区被多个读者进程和写者进程所共享。
读者进程从缓冲区中读取数据,而写者进程将数据写入缓冲区。
本实验目的是通过使用互斥锁、条件变量和信号量等同步机制,构建一个读者写者问题的解决方案。
实验环境:
- 操作系统:Linux
-编程语言:C语言
实验步骤:
1.创建共享内存缓冲区,用于读者和写者的数据传递。
2.创建互斥锁,用于保护共享内存缓冲区的访问。
3.创建条件变量,用于读者和写者之间的协调。
4.创建读者进程和写者进程,模拟读者写者的并发操作。
5.在读者进程中,通过互斥锁保护共享内存缓冲区,读取数据,并更新计数器。
6.在写者进程中,通过互斥锁保护共享内存缓冲区,写入数据,并更新计数器。
7.使用条件变量实现读者优先或写者优先的策略。
实验结果:
通过实验,我成功实现了读者写者问题的解决方案。
使用互斥锁可以保护共享资源的访问,防止读者和写者同时访问。
使用条件变量可以实现读者优先或写者优先的策略。
实验总结:
通过本次实验,我深入了解了读者写者问题,并且掌握了使用互斥锁、条件变量和信号量等同步机制来解决读者写者问题的方法。
在实现过程中,我遇到了一些困难,例如死锁和竞争条件等问题。
通
过调试和改进代码,我成功解决了这些问题,提高了程序的稳定性和性能。
在以后的工作中,我会更加注重并发编程的实践,提高自己解决问题
的能力。
2011211320周俊霞-读者写者问题实验报告(word文档良心出品)
操作系统试验--读者-写者问题周俊霞20112113202011211307班进程同步一.实习要求:本课程实验内容引自《Windows 内核实验教程》(陈向群、林斌等编著,机械工业出版社2002.9)。
在Windows 环境下,创建一个包含n 个线程的控制进程。
用这n 个线程来表示n个读者或写者。
每个线程按相应测试数据文件的要求,进行读写操作。
请用信号量机制分别实现读者优先和写者优先的读者-写者问题。
1.读者-写者问题的读写操作限制:1)写-写互斥;2)读-写互斥;3)读-读允许;2.读者优先的附加限制:如果一个读者申请进行读操作时已有另一读者正在进行读操作,则该读者可直接开始读操作。
写者优先的附加限制:如果一个读者申请进行读操作时已有另一写者在等待访问共享资源,则该读者必须等到没有写者处于等待状态后才能开始读操作。
运行结果显示要求:要求在每个线程创建、发出读写操作申请、开始读写操作和结束读写操作时分别显示一行提示信息,以确信所有处理都遵守相应的读写操作限制。
二.测试数据文件格式测试数据文件包括n 行测试数据,分别描述创建的n 个线程是读者还是写者,以及读写操作的开始时间和持续时间。
每行测试数据包括四个字段,各字段间用空格分隔。
第一字段为一个正整数,表示线程序号。
第一字段表示相应线程角色,R 表示读者是,W 表示写者。
第二字段为一个正数,表示读写操作的开始时间。
线程创建后,延时相应时间(单位为秒)后发出对共享资源的读写申请。
第三字段为一个正数,表示读写操作的持续时间。
当线程读写申请成功后,开始对共享资源的读写操作,该操作持续相应时间后结束,并释放共享资源。
下面是一个测试数据文件的例子:1 R 3 52 W 4 53 R 5 24 R 6 55 W 5.1 3三、与实验相关的API 介绍在本实验中可能涉及的API 有:线程控制:CreateThread 完成线程创建,在调用进程的地址空间上创建一个线程,以执行指定的函数;它的返回值为所创建线程的句柄。
操作系统实验报告reader-writer
操作系统实验报告实验题目:ReaderWriter实验一.实验目的:1.通过编写和调试程序以加深对进程、线程管理方案的理解2.熟悉Windows多线程程序设计方法二.实验原理:读者-写者允许多个读者同时读一个数据对象,因为读文件不会使数据发生混乱,但不允许一个写者进程与其他读者进程或写者进程同时访问该数据对象。
文件是各个进程能互斥访问临界资源,读者进程和写者进程之间互斥。
在读者进程中,可以有多个读者读数据库,在读者进程的计数要互斥,避免发生错误,同时注意当第一个读者进程读时,一定要封锁写者进程。
当读者进程逐渐撤离时,要针对计数变量进行互斥操作,若当前为最后一个读者进程,读完后应唤醒写者进程。
所以应该分四类可能性:1.读者优先权比写者高,并且不用调配。
2.在一个读者已经占有文件的时候,全体读者的优先权才比写者高3.写者的优先权比读者的优先权高4.所有写者的和所有读者有相同的优先权三.实验代码:DataBaseBuffer:import java.awt.*;public class DataBaseBuffer extends Canvas{int[] readWantQ;int[] writerWantQ;String[] wantQ;int frameDelay = 1560;private int writerID;private int readerCount;private int wantCount;private int readerWantCount, writerWantCount;private int writerCount;private int wn, rn; // the number of readers and writersprivate int readTop, readBottom, writerTop, writerBottom;private int wantTop, wantBottom;private Font font;private FontMetrics fm;private boolean readLock = false;private boolean writeLock = false;public DataBaseBuffer( ){resize(500, 300);setBackground(Color.white);font = new Font("TimesRoman", Font.BOLD, 18);fm = getFontMetrics(font);}public void setSize(int readerN, int writerN){rn = readerN;wn = writerN;readTop = readBottom = writerTop = writerBottom = 0;readerCount = writerCount = readerWantCount = writerWantCount = 0;wantTop = wantBottom = 0;wantCount = 0;writerID = 0;readLock = false;writeLock = false;wantQ = new String[rn+wn];writerWantQ = new int[wn];readWantQ = new int[rn];repaint();}public synchronized void enterQueue(String s, int id){wantQ[wantTop] = s + id;wantTop ++;wantCount ++;repaint();}public synchronized void dequeue(String s, int id ){String str;str = s+id;while(!wantQ[0].equals(str)){try{ wait(); } catch(InterruptedException e) { } }for(int i = 0; i < (wantTop-1); i++){wantQ[i] = wantQ[i+1];}wantTop --;wantCount --;repaint();}public synchronized void changePosition(String s, int id) {String str;String tmp;int pos = 0; //to find the posting of 1st writer String wtr;wtr = s+id;while(!(wantQ[pos].equals(wtr))){pos++;}for(int i = 0; i < wantTop; i++){System.out.println(wantQ[i]);}str = wantQ[pos];for(int i = pos; i > 0; i--){wantQ[i] = wantQ[i-1];}wantQ[0] = str;repaint();for(int i = 0; i < wantTop; i++){System.out.println(wantQ[i]);}}public synchronized boolean hasWriterWant(){return (writerWantCount > 0);}public synchronized boolean hasReaderWant(){return (readerWantCount > 0);}public synchronized void acquireReadLock(ReaderWriterApplet applet, int id){readWantQ[readTop] = id; //nums is the index for readWantQreadTop = (readTop+1) % rn;readerWantCount ++;repaint();notifyAll();enterQueue("R", id);applet.r[id].status = 1; //want inapplet.mc.println(applet.r[id].status, "r", id);try{ applet.r[id].sleep(frameDelay);}catch(InterruptedException e) {}if(applet.writerPriority){while(hasWriterWant() || writeLock){applet.r[id].status = 3;applet.mc.println(applet.r[id].status, "r", id);try{ wait(); } catch(InterruptedException e) { } }//end of while loop}//end of if statementelse if(applet.readerPriority){while(readWantQ[readBottom] != id){try { wait(); } catch(InterruptedException e) {} }changePosition("R",id);}else{applet.r[id].status = 3;applet.mc.println(applet.r[id].status, "r", id);while(!wantQ[wantBottom].equals("R"+id)){try{ wait(); } catch(InterruptedException e) { } }}while(writeLock) //if there is any writer is writing {applet.r[id].status = 3;applet.mc.println(applet.r[id].status, "r", id);try{ wait(); } catch(InterruptedException e) { } }if(readLock == false){readLock = true;notifyAll();}readBottom = (readBottom+1) %rn;readerWantCount --;dequeue("R", id);readerCount ++;repaint();applet.r[id].status = 2;applet.mc.println(applet.r[id].status, "r", id);System.out.println("Reader "+id + "is reading");notifyAll();}public synchronized boolean hasReader(){return (readerCount > 0);}public synchronized void releaseReadLock(ReaderWriterApplet applet,int id){readerCount --;notifyAll();if(!hasReader()){readLock = false;notifyAll();applet.r[id].status = 4;applet.mc.println(applet.r[id].status, "r", id);}repaint();}public synchronized void acquireWriteLock(ReaderWriterApplet applet, int id){writerWantQ[writerTop] = id;writerTop=(writerTop+1)%wn;writerWantCount ++;notifyAll();repaint();enterQueue("W", id);applet.w[id].status = 1; //want inapplet.mc.println(applet.w[id].status, "w", id);try{ applet.w[id].sleep(frameDelay); }catch(InterruptedException e) {}if(applet.writerPriority){while(writerWantQ[writerBottom] != id){try{ wait(); } catch(InterruptedException e) { }}changePosition("W", id);while(readLock || writeLock){try{ wait(); } catch(InterruptedException e) { }}}else if(applet.readerPriority){while(!(wantQ[wantBottom].equals("W"+id)) || hasReaderWant() || readLock || writeLock){try{ wait(); } catch(InterruptedException e) { }}System.out.println("Writer "+ id + " move forward");}else{while(!(wantQ[wantBottom].equals("W"+id))){try{ wait(); } catch(InterruptedException e) { }}while(readLock || writeLock){try{ wait(); } catch(InterruptedException e) { }}}writeLock = true;System.out.println("Writer "+ id+ " Got the lock ******");notifyAll();dequeue("W", id);writerBottom = (writerBottom + 1)%wn;writerID = id;writerWantCount --;writerCount++;notifyAll();repaint();applet.w[id].status = 2;applet.mc.println(applet.w[id].status, "w", id);}public synchronized void releaseWriteLock(ReaderWriterApplet applet, int id){System.out.println("Writer " + id + " released the lock");writerCount --;writerID = 0;writeLock = false;notifyAll();repaint();}public void clear(){writerBottom = writerTop = 0;readBottom = readTop = 0;writerWantCount = 0;readerWantCount = 0;readerCount = 0;writerCount = 0;readLock = writeLock = false;writerWantQ = new int[wn];readWantQ = new int[rn];wantQ = new String[wn+rn];wantTop = wantBottom = 0;}public void paint(Graphics g){int xpos = 630;int ypos = 5;g.setFont(new Font("TimesRoman", Font.BOLD, 11));g.setColor(Color.green);g.draw3DRect(xpos, ypos, 10, 10, true);g.fillRect(xpos, ypos, 10, 10);g.drawString("Reading", xpos+15, ypos+10);g.setColor(Color.red);g.draw3DRect(xpos, ypos+14, 10, 10, true);g.fillRect(xpos, ypos+14, 10, 10);g.drawString("Writing", xpos+15, ypos+25);g.setColor(Color.blue);g.draw3DRect(xpos, ypos+28, 10, 10, true);g.fillRect(xpos, ypos+28, 10, 10);g.drawString("Empty", xpos+15, ypos+40);g.setFont(new Font("TimesRoman", Font.BOLD, 14));g.setColor(Color.blue);xpos = 40;ypos = 50;g.drawString("Waiting Queue", xpos-5, ypos-20);int i = wantBottom;for(int j = 0; j < wantCount; j++){if( wantQ[i].equals("W1") || wantQ[i].equals("W2")||wantQ[i].equals("W3")|| wantQ[i].equals("W4")||wantQ[i].equals("W5")){g.setColor(Color.red);g.drawString(wantQ[i], xpos+450-30*j, ypos-18);g.draw3DRect(xpos+445-30*j, ypos-35, 28, 28, true);}if( wantQ[i].equals("R1") || wantQ[i].equals("R2")||wantQ[i].equals("R3")|| wantQ[i].equals("R4")||wantQ[i].equals("R5")){g.setColor(Color.green);g.drawString(wantQ[i], xpos+450-30*j, ypos-18);g.draw3DRect(xpos+445-30*j, ypos-35, 28, 28, true);}i = (i+1) % (wn+rn);}if(readLock) g.setColor(Color.green);else if(writeLock) g.setColor(Color.red);else g.setColor(Color.blue);g.draw3DRect(xpos+250, ypos+20, 100, 100, true);g.fillRect(xpos+250, ypos+20, 100, 100);if(readLock){g.setColor(Color.black);g.drawString("Reading", xpos + 270, ypos+60);}else if(writeLock){g.setColor(Color.black);g.drawString("W " +Integer.toString(writerID), xpos + 280,ypos+45);g.drawString("Writing", xpos + 270, ypos+60);}}}MessageCanvas:import java.awt.*;class MessageCanvas extends Canvas{private Font font;private FontMetrics fm;private int[] writerStatus;private int[] readerStatus;private int msgHeight;private int msgWidth;private int pn, cn;private int frameDelay = 256;public MessageCanvas( ){resize(size().width, 50);setBackground(Color.green);font = new Font("TimesRoman", 1, 18);fm = getFontMetrics(font);msgHeight = fm.getHeight();}public void setMessage(int writerN, int readerN) {pn = writerN;cn = readerN;writerStatus = new int[pn+1];readerStatus = new int[cn+1];repaint();}void println(String s){msgWidth = fm.stringWidth(s);repaint();}void println(int s, String st, int id){if(st.equals("w"))writerStatus[id] = s;elsereaderStatus[id] = s;repaint();}void println(int s, int number, String st, int id){if(st.equals("w")){writerStatus[id] = s;}else{readerStatus[id] = s;}repaint();}public void paint(Graphics g){g.setFont(font);int xpos = 60;int ypos = 40;g.drawString("Status of Readers: ", 60, 20);g.drawString("Status of Writers: ", 360, 20);g.setFont(new Font("TimesRoman", 1, 14));for(int i=1; i<=cn;i++){g.setColor(Color.black);g.drawString("R" + i, xpos, ypos+(15*i+10*(i-1)));if(readerStatus[i] == 0){g.setColor(Color.yellow);g.fillOval(xpos+60, ypos+(2*i+22*(i-1)), 18, 18);g.drawString("Sleeping ...", xpos+120, ypos+(15*i + 10*(i-1)));}else if (readerStatus[i] == 1){g.setColor(Color.gray);g.fillOval(xpos+60, ypos+(2*i+22*(i-1)), 18, 18);g.drawString("Want to read", xpos+120, ypos+(15*i + 10*(i-1)));}else if (readerStatus[i] == 3){g.setColor(Color.gray);g.fillOval(xpos+60, ypos+(2*i+22*(i-1)), 18, 18);g.drawString("Waiting in the queue", xpos+120, ypos+(15*i + 10*(i-1)));}else if (readerStatus[i] == 2){g.setColor(Color.blue);g.fillOval(xpos+60, ypos+(2*i+22*(i-1)), 18, 18);g.drawString("Reading...", xpos+120, ypos+(15*i + 10*(i-1)));}}xpos = 360;ypos = 40;for(int i=1; i<=pn; i++){g.setColor(Color.black);g.drawString("W" + i, xpos, ypos+(15*i+10*(i-1)));if(writerStatus[i] == 0){g.setColor(Color.yellow);g.fillOval(xpos+60, ypos+(2*i+22*(i-1)), 18, 18);g.drawString("Sleeping ...", xpos+120, ypos+(15*i + 10*(i-1)));}else if (writerStatus[i] == 1){g.setColor(Color.gray);g.fillOval(xpos+60, ypos+(2*i+22*(i-1)), 18, 18);g.drawString("Waiting in the queue", xpos+120, ypos+(15*i + 10*(i-1)));}else if (writerStatus[i] == 2){g.setColor(Color.blue);g.fillOval(xpos+60, ypos+(2*i+22*(i-1)), 18, 18);g.drawString("Writing ...", xpos+120, ypos+(15*i + 10*(i-1)));}}}}Reader:public class Reader extends Thread{private DataBaseBuffer buffer;private ReaderWriterApplet tapplet;private int cid;int delay = 6500;int status = 0;public Reader(ReaderWriterApplet applet, DataBaseBuffer db, int id){ buffer = db;tapplet = applet;cid = id;}public void run(){while(true){try{status = 0;tapplet.mc.println(status, "r", cid);sleep((int) (Math.random()*delay));buffer.acquireReadLock(tapplet, cid);sleep((int) (Math.random()*delay));buffer.releaseReadLock(tapplet, cid);} catch(InterruptedException e){System.err.println("Reader Execption " + e.toString());}}}}ReaderWriterApplet:import java.awt.*;import java.awt.event.*;import java.util.*;import java.applet.Applet;import ng.*;public class ReaderWriterApplet extends Applet{private ReaderWriterApplet applet = this;private DataBaseBuffer myBuffer;private int buffersize;private Button fastButton, slowButton, stopButton, startButton, pauseButton, continueButton;private Button stopReaderButton, stopWriterButton;private Panel buttonPanel, priorityPanel, namePanel;private Choice priority, reader, writer;private Thread at;private int readerN = 1;private int writerN = 1;boolean readerPriority = false;boolean writerPriority = false;boolean samePriority = true; //default priority of readers and writers MessageCanvas mc;Reader[] r;Writer[] w;synchronized void startPushed() {notify();}synchronized void stopPushed() {notify();}public void init() {myBuffer = new DataBaseBuffer();mc = new MessageCanvas();resize(800, 600);setLayout(new GridLayout(3, 1));add(myBuffer);add(mc);buttonPanel = new Panel();priorityPanel = new Panel();namePanel = new Panel();Panel bPanel = new Panel(); // to hold all buttons and the labels bPanel.setFont(new Font("TimesRoman", Font.BOLD, 14));bPanel.setLayout(new GridLayout(3, 1));buttonPanel.add(startButton = new Button("START"));buttonPanel.add(stopButton = new Button("STOP"));buttonPanel.add(pauseButton = new Button("PAUSE"));buttonPanel.add(continueButton = new Button("CONTINUE"));buttonPanel.add(fastButton = new Button("FASTER"));buttonPanel.add(slowButton = new Button("SLOWER"));Panel choicePanel = new Panel(); //to hold all the choice boxespriority = new Choice();priority.addItem("Same Priority");priority.addItem("Writers Have Priority");priority.addItem("Readers Have Priority");priority.select("Same Priority");Label priorityLabel = new Label("Priority", 2);priorityLabel.setBackground(Color.lightGray);priorityPanel.add(priorityLabel);priorityPanel.add(priority);choicePanel.add(priorityPanel);reader = new Choice();for(int i = 0; i <=5; i++){reader.addItem(Integer.toString(i));}reader.select("1");Label readerLabel = new Label("Number of Readers", 2);readerLabel.setBackground(Color.lightGray);Panel readerPanel = new Panel();readerPanel.add(readerLabel);readerPanel.add(reader);writer = new Choice();for(int i = 0; i<=5; i++){writer.addItem(Integer.toString(i));}writer.select("1");Label writerLabel = new Label("Number of Writers", 2);writerLabel.setBackground(Color.lightGray);Panel writerPanel = new Panel();writerPanel.add(writerLabel);writerPanel.add(writer);Label nameLabel = new Label("Readers/Writers Animation");nameLabel.setFont(new Font("TimesRoman", Font.BOLD, 18));nameLabel.setForeground(Color.blue);namePanel.add(nameLabel);choicePanel.add(readerPanel);choicePanel.add(writerPanel);bPanel.add(choicePanel);bPanel.add(buttonPanel);bPanel.add(namePanel);add(bPanel);}public boolean action(Event evt, Object arg){if(evt.target == priority){if(arg.equals("Writers Have Priority")){writerPriority = true;readerPriority = false;samePriority = false;}else if(arg.equals("Readers Have Priority")) {readerPriority = true;writerPriority = false;samePriority = false;}else{readerPriority = false;writerPriority = false;samePriority = false;}return true;}else if(evt.target == reader){readerN = Integer.parseInt(arg.toString());return true;}else if(evt.target == writer){writerN = Integer.parseInt(arg.toString());return true;}else if(arg.equals("FASTER")){int newDelay;if(readerN != 0) newDelay = r[1].delay;else newDelay = w[1].delay;newDelay /= 2;newDelay = newDelay < 100 ? 100: newDelay;for(int i = 1; i <= readerN; i++){r[i].delay = newDelay;for(int i = 1; i <= writerN; i++){w[i].delay = newDelay;}return true;}else if(arg.equals("SLOWER")){int newDelay;if(readerN !=0) newDelay = w[1].delay;else newDelay = r[1].delay;newDelay *= 2;for(int i = 1; i <= readerN; i++){r[i].delay = newDelay;}for(int i = 1; i <= writerN; i++){w[i].delay = newDelay;}return true;}else if(arg.equals("PAUSE")){for(int i = 1; i <= readerN; i++){r[i].suspend();}for(int i = 1; i <= writerN; i++){w[i].suspend();}fastButton.setEnabled(false);slowButton.setEnabled(false);return true;}else if(arg.equals("CONTINUE")){for(int i = 1; i <= readerN; i++){if(r[i].isAlive()) r[i].resume();}for(int i = 1; i <= writerN; i++)if(w[i].isAlive()) w[i].resume();}fastButton.setEnabled(true);slowButton.setEnabled(true);return true;}else if(arg.equals("START")){r = new Reader[readerN+1]; //Reader[0] is a dummy slotw = new Writer[writerN+1];System.out.println("readers: "+readerN+" writers: " + writerN);mc.setMessage(writerN, readerN);myBuffer.setSize(readerN, writerN);for(int i = 1; i <= readerN; i++){r[i] = new Reader(applet, myBuffer, i);}for(int i = 1; i <= writerN; i++){w[i] = new Writer(applet, myBuffer, i);}for(int i = 1; i <= writerN; i++){w[i].start();}for(int i = 1; i <= readerN; i++){r[i].start();}fastButton.setEnabled(true);slowButton.setEnabled(true);startButton.setEnabled(false);reader.setEnabled(false);writer.setEnabled(false);priority.setEnabled(false);applet.startPushed();return true;}else if(arg.equals("STOP")){for(int i = 1; i <= readerN; i++){if(r[i].isAlive())r[i].stop();r[i] = null;}for(int i = 1; i <= writerN; i++){if(w[i].isAlive())w[i].stop();w[i] = null;}applet.stopPushed();startButton.setEnabled(true);fastButton.setEnabled(true);slowButton.setEnabled(true);reader.setEnabled(true);writer.setEnabled(true);priority.setEnabled(true);if(at != null) at.stop();at = null;return true;}else{ return false;}}}Writer:public class Writer extends Thread{private DataBaseBuffer buffer;private ReaderWriterApplet tapplet;private int id;int delay = 6500;int status = 0;public Writer(ReaderWriterApplet applet, DataBaseBuffer db, int id){ buffer = db;tapplet = applet;this.id = id;}public void run(){while(true){try{status = 0;tapplet.mc.println(status, "w", id);sleep((int)(Math.random()*delay));buffer.acquireWriteLock(tapplet, id);sleep((int) (Math.random()*delay));buffer.releaseWriteLock(tapplet, id);} catch(InterruptedException e){System.err.println("Execption " + e.toString());}}}}四.实验结果:运行如下:。
读者-写者 操作系统实验报告 计算机操作系统
4.1实验二:读者写者问题4.1.1实验要求在Windows 环境下,创建一个控制台进程,此进程包含n个线程。
用这n个线程来表示n个读者或写者。
每个线程按相应测试数据文件(后面有介绍)的要求进行读写操作。
用信号量机制分别实现读者优先和写者优先的读者-写者问题。
读者-写者问题的读写操作限制(包括读者优先和写者优先):1)写-写互斥,即不能有两个写者同时进行写操作。
2)读-写互斥,即不能同时有一个线程在读,而另一个线程在写。
3)读-读允许,即可以有一个或多个读者在读。
读者优先的附加限制:如果一个读者申请进行读操作时已有另一个读者正在进行读操作,则该读者可直接开始读操作。
写者优先的附加限制:如果一个读者申请进行读操作时已有另一写者在等待访问共享资源,则该读者必须等到没有写者处于等待状态才能开始读操作。
运行结果显示要求:要求在每个线程创建、发出读写操作申请、开始读写操作和结果读写操作时分别显示一行提示信息,以确定所有处理都遵守相应的读写操作限制。
4.1.2测试数据文件格式测试数据文件包括n行测试数据,分别描述创建的n个线程是读者还是写者,以及读写操作的开始时间和持续时间。
每行测试数据包括四个字段,各个字段间用空格分隔。
第一字段为一个正整数,表示线程序号。
第二字段表示相应线程角色,R表示读者,W表示写者。
第三字段为一个正数,表示读写操作的开始时间:线程创建后,延迟相应时间(单位为秒)后发出对共享资源的读写申请。
第四字段为一个正数,表示读写操作的持续时间。
当线程读写申请成功后,开始对共享资源的读写操作,该操作持续相应时间后结束,并释放共享资源。
下面是一个测试数据文件的例子:1 R 3 52 W 4 53 R 5 24 R 6 55 W 5.1 3注意:在创建数据文件时,由于涉及到文件格式问题,最好在记事本中手工逐个键入数据,而不要拷贝粘贴数据,否则,本示例程序运行时可能会出现不可预知的错误。
4.1.3实习分析可以将所有读者和所有写者分别存于一个读者等待队列和一个写者等待队列中,每当读允许时,就从读者队列中释放一个或多个读者线程进行读操作;每当写允许时,就从写者队列中释放一个写者进行写操作。
读者写者问题实验报告
读者写者问题实验报告1. 引言读者写者问题是操作系统中的经典同步问题,用于研究多线程环境下对共享资源的访问和保护。
在该问题中,有多个读者和写者同时对一个共享资源进行操作,需要保证并发访问时的正确性和效率。
通过本实验,我们将探讨读者写者问题的解决方案,并比较不同算法的性能差异。
2. 实验目标本实验的主要目标是通过实现和比较不同的读者写者问题算法,深入了解并发访问的挑战和解决方案。
具体而言,我们将研究以下几个方面:•设计并实现读者写者问题的解决方案•比较不同算法的性能差异•分析可能的优化策略3. 实验方法我们将使用Python编程语言来实现读者写者问题的解决方案。
在实验过程中,我们将尝试以下几种常见的算法:3.1. 读者优先算法在读者优先算法中,当有读者在访问共享资源时,其他读者可以同时访问,但写者需要等待。
只有当所有读者完成访问后,写者才能获得访问权限。
3.2. 写者优先算法在写者优先算法中,当有写者在访问共享资源时,其他读者和写者都需要等待。
只有当写者完成访问后,其他读者或写者才能获得访问权限。
3.3. 公平算法在公平算法中,读者和写者的访问权限是公平的,先到先得。
无论读者还是写者,都需要按照到达的顺序依次获取访问权限。
4. 实验步骤下面是我们实施实验的具体步骤:4.1. 实现基本的读者写者问题解决方案我们首先实现基本的读者写者问题解决方案,包括读者和写者的线程逻辑和共享资源的访问控制。
我们将使用互斥锁和条件变量来保证并发访问的正确性。
4.2. 实现读者优先算法在已有的基本解决方案的基础上,我们实现读者优先算法。
我们将通过优化访问控制的逻辑来实现读者优先的特性。
4.3. 实现写者优先算法类似地,我们在基本解决方案的基础上实现写者优先算法。
我们将调整访问控制的逻辑,使得写者优先于其他读者和写者。
4.4. 实现公平算法最后,我们实现公平算法。
我们将结合队列和条件变量等技术来确保读者和写者的访问顺序是公平的。
读者-写者问题解答计算机操作系统实验报告指导资料
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)读者优先的设计思想是读进程只要看到有其它读进程正在读,就可以继续进行读;写进程必须等待所有读进程都不读时才能写,即使写进程可能比一些读进程更早提出申请。
读者写者问题实验报告
北京电子科技学院(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);// 然后等待}//其设计思想是:读者在读,来了写着,创建写着线程,利用时间片区分他们。
操作系统读者写者问题报告
操作系统读者写者问题报告
读者写者问题是一种典型的操作系统同步问题,其描述如下:有多个读者和写者同时访问共享资源,读者可以同时访问共享资源,但写者必须独占式的访问共享资源,即任何时刻只能有一个写者访问共享资源,且在写者访问共享资源的期间,任何读者都不得访问共享资源。
此外,读者在访问共享资源时不会修改共享资源,而写者则会对共享资源进行修改。
如何实现读者写者问题呢?简单来说,可以使用信号量机制来解决这个问题。
具体来说,可以使用两个信号量RdMutex和WrMutex,RdMutex用于锁定读者,在读者访问共享资源时,需要申请RdMutex信号量,如果有写者在访问共享资源,则RdMutex会阻止读者访问共享资源;而当最后一个读者结束访问共享资源时,需要释放RdMutex信号量,以便让其他等待的读者访问共享资源。
类似地,WrMutex用于锁定写者,在写者访问共享资源时,需要申请WrMutex信号量,如果有其他读者或者写者在访问共享资源,则WrMutex会阻止写者访问共享
资源;而当写者访问共享资源结束时,需要释放WrMutex信号量,以便让其他等待的写者访问共享资源。
除了信号量机制之外,还可以使用其他同步机制来解决读者写者问题,比如互斥量、条件变量等。
同时,操作系统还可以采用优化策略,比如写优先、读写优先等,来提高读写效率。
总之,读者写者问题是操作系统同步问题中的一个经典问题,其实现方式需要考虑多方面的因素,包括并发访问、同步机制、优化策略等,需要经过深入思考和有效实践才能得到较好的解决方案。
读者写者问题实验报告
读者写者问题实验报告引言读者写者问题是计算机科学中经典的同步问题之一,它涉及多线程编程中的资源竞争与同步机制。
通过对读者写者问题的研究,我们可以深入理解线程同步的重要性,并掌握解决并发编程中可能出现的竞争条件和死锁等问题的方法。
在本实验中,我们将设计并实现一个简单的读者写者问题的解决方案,并通过模拟多个读者和写者的并发访问来验证方案的正确性和效果。
问题描述读者写者问题可描述为:有一共享资源(如文件、数据库等),读者可同时访问共享资源进行读取操作,但写者在进行写入操作时,不可同时被其他任何读者或写者访问。
读者和写者的并发访问需要由线程同步机制来保证共享资源的一致性和完整性。
实验设计与实现为了解决读者写者问题,我们需要考虑以下几个关键点:1. 共享资源的访问控制我们可以使用互斥量(Mutex)来实现对共享资源的访问控制。
当一个线程访问共享资源时,它需要先获得互斥量的锁,如果锁已被其他线程占用,则线程进入等待状态,直到锁可用。
一旦线程完成对共享资源的访问,它将释放锁,以便其他线程继续访问。
2. 读者与写者的优先级在读者写者问题中,我们往往需要设定某个优先级规则,以确定读者和写者之间的调度顺序。
一种常见的策略是给予写者优先级,即当一个写者在等待访问共享资源时,其他读者都必须等待。
这样做是为了避免写者长时间等待,以免造成饥饿问题。
3. 记录读者和写者的数量为了控制读者和写者的并发访问,我们需要记录当前同时访问共享资源的读者和写者的数量。
我们可以使用整数变量来记录读者和写者的数量,并通过信号量来保证对这些计数变量的互斥访问。
4. 同步机制的设计在实现读者写者问题的解决方案时,我们需要考虑如何合理地使用互斥量和信号量,并结合优先级规则来实现读者和写者的同步。
这需要通过仔细的设计和调试来确保解决方案的正确性。
实验结果与分析我们基于上述设计实现了一个读者写者问题的解决方案,并进行了多次仿真实验。
实验环境•操作系统:Windows 10•编程语言:C++•编译器:GCC实验步骤1.编写读者和写者线程的代码,其中涉及到对共享资源的读取和写入操作,以及对计数变量和互斥量的访问操作。
操作系统读者写者实验报告
g_hReadSemaphore = CreateSemaphore(NULL,1,100,NULL); //创建信号 灯,当前可用的资源数为1,最大为100 g_hWriteSemaphore = CreateSemaphore(NULL,1,100,NULL); //创建信号 灯,当前可用的资源数为1,最大为100 CreatePersonList(g_PersonLists); // Create All the reader and writers printf("Created all the reader and writer\n...\n"); g_CurrentTime = 0; while(true) { g_CurrentTime++; Sleep(300); // 300 ms printf("CurrentTime = %d\n",g_CurrentTime); if(finished) return 0; } // return 0; } void CreatePersonList(int *pPersonLists) { int i=0; int *pList = pPersonLists; bool Ret; while(pList[0] != END) { switch(pList[1]) { case R: Ret = CreateReader(pList[2],pList[3],pList[0]);//351,w452,523,654 break; case W: Ret = CreateWriter(pList[2],pList[3],pList[0]);
. Perform reader operation; Ssignal(L,1); Until false; End Writer :begin Repeat Swait(mx ,1,1,l,RN,0); Perform writer operation; Ssignal(mx,1); Until false; End Parend End 其中,Swait(mx,1,0)语句起着关作用,只要无Writer进程进入 些,mx=1,reader进程就都可以进入读。但是要一旦有Writer进程进入 写时,其MX=0,则任何reader进程就都无法进入读。Swait(mx ,1,1,l,RN,0)语句表示仅当既无Write进程在写(mx=1),又无reader进程 在读(L=RN)时,writer进程才能进入临界区写。 本设计方案就是通过利用记录型信号量对读者写者问题的解决过程 进行模拟演示,形象地阐述记录型信号量机制的工作原理。
读者写者问题实验报告
操作系统读者-写者问题模拟读者-写者问题模拟目录操作系统读者-写者问题模拟----------------------------------------------------------------------------- - 1 -一、设计概述 ------------------------------------------------------------------------------------------------------- - 2 -二、设计目的与内容 ---------------------------------------------------------------------------------------------- - 3 -一、实验目的--------------------------------------------------------------------------------------------------- - 3 -二、实验内容--------------------------------------------------------------------------------------------------- - 3 -三、设计分析--------------------------------------------------------------------------------------------------- - 3 -四. 程序实现 --------------------------------------------------------------------------------------------------------- - 4 -五、程序调试 --------------------------------------------------------------------------------------------------------- - 4 -六、结果分析和讨论------------------------------------------------------------------------------------------------ - 4 -七、源程序 ------------------------------------------------------------------------------------------------------------ - 5 -一、设计概述所谓读者写者问题,是指保证一个writer进程必须与其它进程互斥地访问共享对象的同步问题。
操作系统实验报告-pv操作-读者写着-linux
五、 相关函数及操作 相关函数: (1) pthread_create UNIX 环境创建线程函数,具体格式: int pthread_create(pthread_t *restrict tidp,const pthread_attr_t *restrict attr,void*(*start_rtn)(void*),void *restrict arg); 返回值:若成功则返回 0,否则返回出错编号 返回成功时,由 tidp 指向的内存单元被设置为新创建线程的线程 ID。 attr 参数用于制定各种不同的线程属性。新创建的线程从 start_rtn 函数
本原理,增强了自己的动手能力。
课程设计中也实践了 windows 操作系统中创建进程,发现了两者的不同: linux 操作系统仅通过 pv 操作实现进程的同步与互斥,而 windows 操作系统 还有同步量,临界区的操作。
学会了运行及操作虚拟机,在课程设计中遇到了困难独立查找相关资料 也可以很快地解决。
sem_wait(&mutex) ; readcount -- ; if ( readcount == 0 && writecount>0 )
sem_post(&sw) ; sem_post(&mutex) ; } void writer(void *arg)
{ printf("Writer %d sents the writing require.\n",(int *)arg);
(4) sem_post 函数 sem_post( sem_t *sem )用来增加信号量的值。当有线程阻塞在
这个信号量上时,调用这个函数会使其中的一个线程不在阻塞,选择机 制同样是由线程的调度策略决定的。
读者写者实验报告
操作系统原理实验报告实验名称:操作系统姓名: XXX学号: xxxxxxxxxx班级: xxx指导老师: xxx一、实验内容在Windows2000环境下,创建一个控制台进程,此进程包含n个线程。
用这n个线程来表示n个读者或写者。
每个线程按相应测试数据文件(后面有介绍)的要求进行读写操作。
用信号量机制分别实现读者优先和写者优先的读者-写者问题。
读者-写者问题的读写操作限制(包括读者优先和写者优先):1)写-写互斥,即不能有两个写者同时进行写操作。
2)读-写互斥,即不能同时有一个线程在读,而另一个线程在写。
,3)读-读允许,即可以有一个或多个读者在读。
读者优先的附加限制:如果一个读者申请进行读操作时已有另一个读者正在进行读操作,则该读者可直接开始读操作。
写者优先的附加限制:如果一个读者申请进行读操作时已有另一写者在等待访问共享资源,则该读者必须等到没有写者处于等待状态后才能开始读操作。
运行结果显示要求:要求在每个线程创建、发出读写操作申请、开始读写操作和结束读写操作时分别显示一行提示信息,以确定所有处理都遵守相应的读写操作限制。
二、实验目的在Windows2000环境下,创建一个控制台进程,此进程包含n个线程。
用这n 个线程来表示n个读者或写者。
每个线程按相应测试数据文件(后面有介绍)的要求进行读写操作。
用信号量机制分别实现读者优先和写者优先的读者-写者问题。
三、实验原理1).读者优先读者优先指的是除非有写者在写文件,否则读者不需要等待。
所以可以用一个整型变量read_count记录当前的读者数目,用于确定是否需要释放正在等待的写者线程(当read_count=O时,表明所有的读者读完,需要释放写者等待队列中的一个写者)。
每一个读者开始读文件时,必须修改read_count变量。
因此需要一个互斥对象mutex来实现对全局变量read_count修改时的互斥。
另外,为了实现写-写互斥,需要增加一个临界区对象write。
操作系统读者写者实验报告
操作系统读者写者实验报告一、实验目的通过实验理解读者写者问题的实现原理,掌握相关的同步机制,实现读者写者问题的经典解法,并对比不同解法的优缺点。
二、实验原理1.读者写者问题读者写者问题是指在多个线程同时读写一个共享数据的情况下可能出现的问题。
其问题的核心在于多个读线程可以同时读,但只能有一个写线程能够写,并且在写操作过程中不能有任何的读操作。
2.互斥与同步为了解决读者写者问题,在多线程并发读写共享数据时,需要使用互斥与同步机制来保证数据的完整性和一致性。
-互斥:通过锁机制来保证只允许一个线程进入临界区,其他线程需要等待锁的释放。
-同步:通过信号量等机制来保证线程按照一定顺序执行。
三、实验步骤本次实验中将实现两个版本的读者写者问题解决方案:一是使用互斥锁和条件变量,二是使用信号量。
1.使用互斥锁和条件变量(1)定义全局变量和互斥锁:共享数据、读者数目、互斥锁、写者条件变量、读者条件变量。
(2)初始化互斥锁和条件变量。
(3)写者线程的实现:获取互斥锁,判断当前是否有读者或写者,如果有则等待条件变量,然后进行写操作,释放互斥锁。
(4)读者线程的实现:获取互斥锁,判断是否有写者,如果有则等待条件变量,否则增加读者数目并释放互斥锁,进行读操作。
(5)测试程序的运行并输出结果。
2.使用信号量(1)定义全局变量和信号量:共享数据、读者信号量、写者信号量、用于保护读者数目和写者数目的互斥信号量。
(2)初始化信号量和互斥信号量。
(3)写者线程的实现:首先获取写者互斥信号量,然后获取写者信号量,进行写操作,释放写者信号量和写者互斥信号量。
(4)读者线程的实现:首先获取读者互斥信号量,然后增加读者数目,如果是第一个读者则获取写者信号量,然后进行读操作,释放读者信号量和读者互斥信号量,如果是最后一个读者则释放写者信号量。
(5)测试程序的运行并输出结果。
四、实验结果与分析通过对比两种解决方案,可以得出以下结论:1.使用互斥锁和条件变量的解决方案相对较为简单,但可能存在饥饿问题,即可能会导致一些线程一直无法访问共享资源。
操作系统读者写者实验报告
《操作系统原理》课程设计课程设计起止时间:2009年11月30日至12月11日指导教师:成绩:课程设计成绩评定表一.设计说明(四号,宋体,加粗)通过学习操作系统,与之前的语句基础相结合,用C语言来编写读者写着问题。
读者写者问题(read—write problem)是一个经典的并发程序设计问题。
有两组并发进程:读者和写者,共享一个问题F,要求:(1)允许多个读者可同时对之执行读操作;(2)只允许一个写者往文件中写信息;(3)任一写者在完成写操作之前不允许其他读者或者写者工作;(4)写者执行写操作前,应让已有的写者和读者全部退出。
二.工作原理(四号,宋体,加粗)读者和写者问题是典型是经典的进程同步问题,进程同步任务是使并发的诸进程之间有效的共享资源,相互合作,从而保证程序的可再现性。
在读者—写者问题中,允许多个读者同时读一个数据对象,因为读文件不会使数据发生混乱,但绝不允许一个写者进程与其他读者进程或写者进程同时访问该数据对象。
文件是诸进程能互斥访问临界资源,读者进程和写者进程,写者进程和写者进程之间的互斥。
在读者进程中,可以有多个读者在读数据库,在读者进程的计数要互斥,以免发生错误,同时注意当第一个读者进程读时,一定要封锁写者进程。
当读者进程逐渐撤离时,也要针对计数变量进行互斥操作,若当前为最后一个读者进程时,读完后,则唤醒写者进程。
当写者进程在进行写操作时,可以封锁其他读者或写者进程,当写操作完成时,唤醒其他读者或写者进程。
所以分析了以下4种可能发生的情况:第 1 种情况: 读者的优先权比写者高,而且,不用调配。
所有读者的优先权都比写者的优先权高,而且,不用调配。
一个读者需要等待的唯一情况是,一个写者已经占用了文件。
一个写者可以取得文件的条件是,没有一个读者处在等待状态或正在读文件。
允许读者们结盟,以便能长期占用文件,而禁止写者的写。
第 2 种情况: 在一个读者已经占有了文件的时候,全体读者的优先权才比写者高。
读者写者实验报告
操作系统原理实验报告实验名称:操作系统姓名: XXX学号: xxxxxxxxxx班级: xxx指导老师: xxx一、实验内容在Windows2000环境下,创建一个控制台进程,此进程包含n个线程。
用这n个线程来表示n个读者或写者。
每个线程按相应测试数据文件(后面有介绍)的要求进行读写操作。
用信号量机制分别实现读者优先和写者优先的读者-写者问题。
读者-写者问题的读写操作限制(包括读者优先和写者优先):1)写-写互斥,即不能有两个写者同时进行写操作。
2)读-写互斥,即不能同时有一个线程在读,而另一个线程在写。
,3)读-读允许,即可以有一个或多个读者在读。
读者优先的附加限制:如果一个读者申请进行读操作时已有另一个读者正在进行读操作,则该读者可直接开始读操作。
写者优先的附加限制:如果一个读者申请进行读操作时已有另一写者在等待访问共享资源,则该读者必须等到没有写者处于等待状态后才能开始读操作。
运行结果显示要求:要求在每个线程创建、发出读写操作申请、开始读写操作和结束读写操作时分别显示一行提示信息,以确定所有处理都遵守相应的读写操作限制。
二、实验目的在Windows2000环境下,创建一个控制台进程,此进程包含n个线程。
用这n 个线程来表示n个读者或写者。
每个线程按相应测试数据文件(后面有介绍)的要求进行读写操作。
用信号量机制分别实现读者优先和写者优先的读者-写者问题。
三、实验原理1).读者优先读者优先指的是除非有写者在写文件,否则读者不需要等待。
所以可以用一个整型变量read_count记录当前的读者数目,用于确定是否需要释放正在等待的写者线程(当read_count=O时,表明所有的读者读完,需要释放写者等待队列中的一个写者)。
每一个读者开始读文件时,必须修改read_count变量。
因此需要一个互斥对象mutex来实现对全局变量read_count修改时的互斥。
另外,为了实现写-写互斥,需要增加一个临界区对象write。
读者写者问题实验报告
读者写者问题实验报告1.实验目的:掌握读者写者问题的基本概念和操作实现方法。
2.实验原理:(1)读者写者问题:1.读者优先:若读者进程正在读文件,写者进程需等待。
2.写者优先:若写者进程正在写文件,读者进程需等待。
3.公平竞争:读写者进程均有机会访问文件。
(2)进程同步:1.信号量:能够同步进程的执行,性能较好。
2.互斥量:能够同步进程的执行,提供了更细粒度的控制。
3.条件变量:让进程能够进行相互之间的协作。
3.实验内容:(1)依照读者写者问题的操作实现方法,采用信号量机制,编写读者进程和写者进程。
(2)测试不同读者写者优先级下程序的执行情况。
4.实验步骤:(1)设计程序架构:1.使用信号量实现读者写者访问文件的同步操作;2.设计Readers和Writers两个类分别实现读者和写者进程的操作。
(2)实现程序:1.编写读者进程,在进程对文件进行读操作之前使用信号量P操作,读取完成后使用信号量V操作;2.编写写者进程,在进程对文件进行写操作之前使用信号量P操作,写入完成后使用信号量V操作;3.设计信号量的初始值,以实现不同读者写者优先级下程序的执行情况。
(3)测试程序:在有多个读者进程和多个写者进程的情况下,测试不同读者写者优先级下程序的执行情况。
5.实验结果:(1)读者优先:读者优先的情况下,不管读者进程和写者进程的数量如何设置,读者总是有后进先出的机会访问文件。
(2)写者优先:写者优先的情况下,不管读者进程和写者进程的数量如何设置,写者总是有先进先出的机会访问文件。
(3)公平竞争:公平竞争的情况下,读者或写者进程均有机会访问文件。
6.实验结论:(1)在实现读者写者问题的过程中,需要采用进程同步技术来确保进程之间的正确协作。
(2)信号量提供了一种较为有效的进程同步机制,能够满足读者写者问题的操作需求。
(3)采用不同的优先级设置,可以使读者写者进程之间实现不同的访问策略,进而实现不同的访问效果。
操作系统实验报告
设计一读者写者问题实习环境:系统为Windows XP + VC 6.0一、实验目的:1、加深对进程概念的理解,明确进程和程序的区别,进一步认识并发执行的实质;2、理解和运用信号量、PV原语、进程间的同步互斥关系等基本知识。
二、设计要求在Windows XP下创建一个控制台进程,该进程应包含n个线程。
用这n个线程来表示n个读者或写者。
每个线程按相应测试数据文件(后面介绍)的要求进行读写操作。
用信号量机制分别实现读者优先和写者优先的读者-写者问题。
读者-写者问题的操作限制(包括读者优先和写者优先):1)写-写互斥,即不能有两个写者同时进行写操作。
2)读-写互斥,即不能同时有一个线程在读,而另一个线程在写。
3)读-读互斥,即可以有一个或多个读者在读。
读者优先的附加限制:如果一个读者申请进行读操作时已有另一个读者正在进行读操作,则该读者可直接开始读操作。
写者优先的附加限制:如果一个读者申请进行读操作时已有另一个写者在等待访问共享资源,则该读者必须等到没有写者出于等待状态后才能开始读操作。
测试文件格式说明,下面是一个测试数据文件的例子:1 R 3 52 W 4 53 R 5 24 R 6 55 W 5.1 36 R 15 47 R 15 4三、设计说明1、读者优先指除非有写者在写文件,否则读者不需要等待。
所以可以用一个整形变量readnum记录当前的读者数目,用于确定是否需要唤醒正在等待的写者进程(当readnum==读者人数时,表明所有的读者读完,需要唤醒写者等待队列中的第一个写者)。
每一个读者开始读文件时,必须修改readnum变量。
因此需要一个互斥对象rnum[]来实现对全局变量readnum修改时的互斥。
另外,为了实现写写互斥,需要增加一个临界区对象wstate。
当写者发出写请求时,必须申请临界区对象的所有权。
通过这种方法,也可以实现读写互斥,当readnum=2时(即第一个读者到来时),读者进程也必须申请临界区对象的所有权。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
《操作系统》上机实验报告实验项目读者写者学院(部)信息学院专业计算机科学与技术班级学生姓名学号读者写者问题一.实验目的:1.熟悉读者优先和写者优先的过程。
2.更好地理解进程同步的概念及其实现方法。
二.实验要求:分别实现读者优先和写者优先。
“读-写”互斥,即不能同时有一个读者在读,同时去有一个写者在写;“写-写”互斥,即不能有两个写者同时进行写操作;“读-读”允许,即可以有两个以上的读者同时进行读操作。
三.实验内容:读者优先:如果没有写者正在操作,则读者不需要等待,用一个整型变量readcount 记录当前的读者数目,用于确定是否释放写者线程,(当readcout=0 时,说明所有的读者都已经读完,释放一个写者线程),每个读者开始读之前都要修改readcount,为了互斥的实现对readcount 的修改,需要一个互斥对象Mutex来实现互斥。
另外,为了实现写-写互斥,需要一个临界区对象write,当写者发出写的请求时,必须先得到临界区对象的所有权。
通过这种方法,可以实现读写互斥,当readcount=1 时,(即第一个读者的到来时,),读者线程也必须申请临界区对象的所有权.当读者拥有临界区的所有权,写者都阻塞在临界区对象write上。
当写者拥有临界区对象所有权时,第一个判断完readcount==1 后,其余的读者由于等待对readcount的判断,阻塞在Mutex上!写者优先:写者优先和读者优先有相同之处,不同的地方在:一旦有一个写者到来时,应该尽快让写者进行写,如果有一个写者在等待,则新到的读者操作不能读操作,为此添加一个整型变量writecount,记录写者的数目,当writecount=0时才可以释放读者进行读操作!为了实现对全局变量writecount的互斥访问,设置了一个互斥对象Mutex3。
为了实现写者优先,设置一个临界区对象read,当有写者在写或等待时,读者必须阻塞在临界区对象read上。
读者除了要一个全局变量readcount实现操作上的互斥外,还需要一个互斥对象对阻塞在read这一个过程实现互斥,这两个互斥对象分别为mutex1和mutex2。
四.实验结果1.实验数据:读者优先:r w r w r 写者优先:r w r w r结果展示:五.实验总结这次实验分读者优先和写者优先来处理,不仅掌握了读者写者的过程和原理,而且还了解到了读者优先和写者优先之间的联系,共同点和不同点。
写代码的过程中出现了许多的问题,最先开始没有用进程来实现,发现比较困难,而且模拟的不真实,后来有从网上面学习了一些进程的东西,借鉴了他人的一些经验完成了这次的报告。
六.实验代码#include <windows.h>#include <conio.h>#include "fstream.h"int readcount=0; //读者数目int writecount=0; //写者数目CRITICAL_SECTION RP_Write; //临界区CRITICAL_SECTION cs_Write;CRITICAL_SECTION cs_Read;struct ThreadInfo //线程信息{ int Threadhao; //线程序号char ThreadClass; //线程类别double ThreadStartTime; //线程开始时间double ThreadRunTime; //线程读写持续时间};void ReaderFun(char* file);//读者优先函数void R_ReaderThread(void *p);//处理读者优先读者线程void R_WriterThread(void *p);//处理读者优先写者线程void WriterFun(char* file);void W_ReaderThread(void *p);void W_WriterThread(void *p);int main()//主函数{char select;while (true){cout<<"1:读者优先"<<endl;cout<<"2:写者优先"<<endl;cout<<"3:退出"<<endl;cout<<" "<<endl;cout<<"请选择要进行的操作:"<<endl;do{cin>>select;if(select!='1' && select!='2' && select!='3')cout<<"你操作有误,请重试!"<<endl;}while (select!='1' && select!='2' && select!='3');system("cls");if (select=='3')return 0;//退出else if (select=='1')//调用读者优先ReaderFun("110.txt");else if(select=='2')//调用写者优先WriterFun("110.txt");cout<<"\n是否还有继续? 1. 继续 2.退出"<<endl;;do{cin>>select;if(select!='1' && select!='2' )cout<<"你操作有误,请重试!"<<endl;}while (select!='1' && select!='2');if(select=='2')return 0;// 退出system("cls");}return 0;}//读者优先函数void ReaderFun(char* file){DWORD n_thread=0; //线程数初值为0DWORD thread_ID; //线程IDDWORD wait_for_all; //等待所有线程结束//临界资源HANDLE h_Mutex;//互斥对象(h_Mutex)确保线程拥有对单个资源的互斥访问权h_Mutex=CreateMutex(NULL,FALSE,"mutex_for_readcount");HANDLE h_Thread[64]; //线程对象数组,最大64ThreadInfo thread_info[64];readcount=0;InitializeCriticalSection(&RP_Write); //初始化临界区ifstream inFile;inFile.open(file);cout<<"读者优先:\n"<<endl;while (inFile){//读入每一个读者、写者的信息inFile>>thread_info[n_thread].Threadhao>>thread_info[n_thread].ThreadClass>>thread_info[n_thread].ThreadStartTime>>thread_info[n_thread].ThreadRunTime;if (-1 == inFile.get())break;n_thread++;//线程数加一}for (int i=0;i<(int)(n_thread);i++){if (thread_info[i].ThreadClass=='r')//创建读者线程h_Thread[i]=CreateThread(NULL,0,\(LPTHREAD_START_ROUTINE)(R_ReaderThread),\&thread_info[i],0,&thread_ID);else//创建写者线程h_Thread[i]=CreateThread(NULL,0,\(LPTHREAD_START_ROUTINE)(R_WriterThread),\&thread_info[i],0,&thread_ID);}wait_for_all=WaitForMultipleObjects(n_thread,h_Thread,TRUE,-1);cout<<"所有的读者和写者线程完成操作."<<endl;}//读者优先-----读者线程void R_ReaderThread(void *p){//互斥变量HANDLE h_Mutex;h_Mutex=OpenMutex(MUTEX_ALL_ACCESS,FALSE,"mutex_for_readcount");DWORD wait_for_mutex; //等待互斥变量所有权DWORD m_delay; //延迟时间DWORD m_ThreadRunTime; //读文件持续时间int m_Threadhao; //线程序号m_Threadhao=((ThreadInfo *)(p))->Threadhao;m_delay=(DWORD)(((ThreadInfo *)(p))->ThreadStartTime*100);m_ThreadRunTime=(DWORD)(((ThreadInfo *)(p))->ThreadRunTime*100);Sleep(m_delay); //延迟等待cout<<"读者线程"<<m_Threadhao<<" 发出读请求."<<endl;//等待互斥对象通知wait_for_mutex=WaitForSingleObject(h_Mutex,-1); //等待互斥信号,保证对readcount的访问、//修改互斥readcount++; //读者数目加一if (readcount==1)EnterCriticalSection(&RP_Write);//禁止写者进入ReleaseMutex(h_Mutex);//释放互斥对象,允许下个读者继续读://读文件cout<<"读者线程"<<m_Threadhao<<" 开始读文件."<<endl;Sleep(m_ThreadRunTime);//退出线程cout<<"读者线程"<<m_Threadhao<<" 完成读文件."<<endl;wait_for_mutex=WaitForSingleObject(h_Mutex,-1); //等待互斥信号,保证对readcount的访问、修改互斥readcount--; //读者数目减少if (readcount==0)LeaveCriticalSection(&RP_Write); //如果所有读者读完,唤醒写者ReleaseMutex(h_Mutex);//释放互斥信号}//读者优先-----写者线程void R_WriterThread(void *p){DWORD m_delay; //延迟时间DWORD m_ThreadRunTime; //读文件持续时间int m_Threadhao; //线程序号//从参数中获得信息m_Threadhao=((ThreadInfo *)(p))->Threadhao;m_delay=(DWORD)(((ThreadInfo *)(p))->ThreadStartTime*100);m_ThreadRunTime=(DWORD)(((ThreadInfo *)(p))->ThreadRunTime*100);Sleep(m_delay); //延迟等待cout<<"写者线程"<<m_Threadhao<<" 发出写请求."<<endl;EnterCriticalSection(&RP_Write);//禁止下一位写者进入//写文件cout<<"写者线程"<<m_Threadhao<<" 开始写文件."<<endl;Sleep(m_ThreadRunTime);//退出线程cout<<"写者线程"<<m_Threadhao<<" 完成写文件."<<endl;LeaveCriticalSection(&RP_Write); //如果所有读者读完,唤醒写者}//写者优先处理函数void WriterFun(char* file){DWORD n_thread=0; //线程数目DWORD thread_ID; //线程IDDWORD wait_for_all; //等待所有线程结束//互斥对象HANDLE h_Mutex1, h_Mutex2, h_Mutex3;h_Mutex1 = CreateMutex(NULL, FALSE, "mutex_for_writecount");h_Mutex2 = CreateMutex(NULL, FALSE, "mutex_for_readcount");h_Mutex3 = CreateMutex(NULL, FALSE, "mutex_for_read");//线程对象数组HANDLE h_Thread[64];ThreadInfo thread_info[64];readcount=0; //初始化readcountInitializeCriticalSection(&cs_Write); //初始化临界区InitializeCriticalSection(&cs_Read);ifstream inFile;inFile.open(file); //打开文件cout<<"写者优先:\n"<<endl;while (inFile){//读入每一个读者、写者的信息inFile>>thread_info[n_thread].Threadhao>>thread_info[n_thread].ThreadClass>>thread_info[n_thread].ThreadStartTime>>thread_info[n_thread].ThreadRunTime;if(-1 == inFile.get())break;n_thread++;//线程数加一}for (int i=0;i<(int)(n_thread);i++){if (thread_info[i].ThreadClass=='r')//创建读者线程h_Thread[i]=CreateThread(NULL,0,\(LPTHREAD_START_ROUTINE)(W_ReaderThread),\&thread_info[i],0,&thread_ID);else//创建写者线程h_Thread[i]=CreateThread(NULL,0,\(LPTHREAD_START_ROUTINE)(W_WriterThread),\&thread_info[i],0,&thread_ID);}//等待所有线程结束wait_for_all=WaitForMultipleObjects(n_thread,h_Thread,TRUE,-1);cout<<"所有的读者和写者线程完成操作."<<endl;}//写者优先-----写者线程void W_WriterThread(void *p){//互斥变量HANDLE h_Mutex1;h_Mutex1 = OpenMutex(MUTEX_ALL_ACCESS,FALSE,"mutex_for_writecount");DWORD wait_for_mutex; //等待互斥变量所有权DWORD m_delay; //延迟时间DWORD m_ThreadRunTime; //读文件持时续间int m_Threadhao; //线程序号m_Threadhao=((ThreadInfo *)(p))->Threadhao;m_delay=(DWORD)(((ThreadInfo *)(p))->ThreadStartTime*100);//每秒时钟中断100次m_ThreadRunTime=(DWORD)(((ThreadInfo *)(p))->ThreadRunTime*100);Sleep(m_delay);cout<<"写者线程"<<m_Threadhao<<" 发出写请求."<<endl;wait_for_mutex=WaitForSingleObject(h_Mutex1,-1);writecount++;if (writecount==1)EnterCriticalSection(&cs_Read);ReleaseMutex(h_Mutex1);EnterCriticalSection(&cs_Write);cout<<"写者线程"<<m_Threadhao<<" 开始写文件."<<endl;Sleep(m_ThreadRunTime);cout<<"写者线程"<<m_Threadhao<<" 完成写文件."<<endl;LeaveCriticalSection(&cs_Write);wait_for_mutex=WaitForSingleObject(h_Mutex1,-1);writecount--;if(writecount == 0)LeaveCriticalSection(&cs_Read);ReleaseMutex(h_Mutex1);}//写者优先-----读者线程void W_ReaderThread(void *p){HANDLE h_Mutex2, h_Mutex3;h_Mutex2 = OpenMutex(MUTEX_ALL_ACCESS,FALSE,"mutex_for_readcount");h_Mutex3 = OpenMutex(MUTEX_ALL_ACCESS,FALSE,"mutex_for_read");DWORD wait_for_mutex, wait_for_mutex1;//等待互斥变量所有权DWORD m_delay; //延迟时间DWORD m_ThreadRunTime; //读文件持续时间int m_Threadhao; //线程序号m_Threadhao=((ThreadInfo *)(p))->Threadhao;m_delay=(DWORD)(((ThreadInfo *)(p))->ThreadStartTime*100);m_ThreadRunTime=(DWORD)(((ThreadInfo *)(p))->ThreadRunTime*100);Sleep(m_delay);cout<<"读者线程"<<m_Threadhao<<" 发出读请求."<<endl;wait_for_mutex1=WaitForSingleObject(h_Mutex3,-1);EnterCriticalSection(&cs_Read);LeaveCriticalSection(&cs_Read);ReleaseMutex(h_Mutex3);wait_for_mutex=WaitForSingleObject(h_Mutex2,-1);readcount++;if (readcount == 1)EnterCriticalSection(&cs_Write);ReleaseMutex(h_Mutex2);cout<<"读者线程"<<m_Threadhao<<" 开始读文件."<<endl;Sleep(m_ThreadRunTime);cout<<"读者线程"<<m_Threadhao<<" 完成读文件."<<endl;wait_for_mutex=WaitForSingleObject(h_Mutex2,-1);readcount--;if (readcount == 0)LeaveCriticalSection(&cs_Write);ReleaseMutex(h_Mutex2);}。