1、计算机操作系统实践教学课程报告题 目 java 编写的信号量解决读者-写者问题学 生 李腾龙学 号 20094666指导教师 李自强 副教授年 级 2009 级专 业 计算机科学与技术学 院 信息与工程技术学院 一 程序运行结果图:a) 写者优先时,当一个写进程发送写请求时,不允许新的读者进行读操作,执行完,读者和写者人数均是 0。b) 读者优先时,当存在读者时,写者将被延迟。二 问题解决过程及思路:a) 有两组并发进程:读操作按钮和写操作按钮分别用(Math.random() * 2) + 1 来随机延迟1,3)秒的时间实现两组并发进程。b) 问题解决:i. 各类的主要功效:MainEnte
2、r 类:入口类;界面初始化,定义的事件处理器对读、写操作按钮,读写优先切换按钮进行事件处理,用R,W 两个字符标示读,写操作,启动读写线程ReadWriteThread.MainFrame 类:界面类;完成了界面的布局。ReadWriteThread 类:读写线程类,进行读,写操作。run()方法,根据 R,W 的标示,分别执行读线程方法 runReader()和写线程方法 runWriter().ReaderCritical 类:读者临界区,用 syncgribuzed 关键字定义进入临界区方法 enterCritical()和离开临界区方法leaveCritical()。WriterCri
3、tical 类:写者临界区。ii. 要求:允许多个读者同时对文件执行读操作:解决:首先,在读者临界区和写者临界区类中,用synchronized 关键字定义进入临界区方法 enterCritical()和离开临界区方法 leaveCritical(),使得同一时间只能有一个ReaderCritical 类型的对象调用此方法;其次,定义读写线程 ReadWriteThread 类中加了对象锁的 readStart()方法,进入读者临界区 readerCritical.enterCriticalSection(),读者人数自加 readerNumber+,if 读者人数 readerNumber
4、= 1时,进入写者临界区 writerCritical.enterCriticalSection(),等待写者写结束,之后不再允许写操作;离开读者临界区readerCritical.leaveCriticalSection(),下次如果不是第一个读者,不再进入写锁,直接进行读操作;最后,执行readStop()方法,读者人数 readerNumber-,如果读者人数等于 0 时,离开写者临界区。iii. 要求:只允许一个写者对文件执行写操作:解决:首先,在执行读操作时,一旦没有写者,读者会进入写者临界区 writerCritical.enterCriticalSection(),直到最后读者人
5、数等于 0 时,离开写者临界区,因此,写者执行写操作,进入写者临界区时,需等待,直到没有读者为止;其次,每个写者进行写操作时,必须首先进入写者临界区,而 synchronized 关键字定义的方法,使得同一时间同步方法不允许被多次调用,这就保证了不可能有两个写者同时工作。所以,只允许一个写着对文件执行写操作。iv. 要求:任何写者在完成操作前不允许其他读者或写者工作。解决:首先,第一个读者进行读操作时,会进入读者临界区,占去读锁,然后进入写者临界区,而写者未完成写操作时,占去了写锁,使得第一个读者就无法进行读操作,后面因读锁被占去也无法工作;其次,一个写者写操作未完成时,占去了写锁,使得任何其
6、他的写者也无法进行工作。v. 要求:写者优先时,写者申请写工作后,不再允许新的读者工作;读者优先时,当存在读者时,随后而来的读者都将允许访问文件,写者必须等待。解决:首先,写者和读者优先级是通过读写切换按钮每次根据上次优先级更改读写线程类中的静态整型变量priority 的值, priority = 1 时是写者优先,priority = 2 时是读者优先;其次,在进行写操作的 writeStart()方法处理中,if(priority = 1)时,即写者优先,进入读者临界区readerCritical.enterCriticalSection(),占去读锁,不再允许其他的新读者工作,然后进入
7、写者临界区,有读者时等待;最后,if(priority = 2)时,即读者优先,直接进入写者临界区,有读者时等待,而只要有一个读者正在工作时,其他读者不再需要写锁,直接进行读工作。c) 界面解释。1. 读者人数显示框:MainFrame 对象.JTextField:在每次读者进行读线程的执行时,发送了读请求后,调用readStart()方法,在每次执行开始读后,MainEnter.frame.textReader.setText(new Integer(readerNumber).toString(),改变显示框中的值。runReader()中读完时,调用 readStop()方法,将读者人数
8、自减 1,MainEnter.frame.textReader.setText(new Integer(readerNumber).toString(),改变显示框中的值。2. 写者显示框:同上,只是执行方法分别是,writeStart()和 writeStop()。3. 信息显示框:MainFrame 对象.TextArea.在每次执行相应的操作后,就将相应的显示内容,利用MainEnter.frame.textMessage.append(date.getHours() + “:“ + date.getMinutes() + “:“ + date.getSeconds() + “ “ +
9、serial + “号读线程“ + “结束读n“) ,将信息附加到显示域的后面,serial 变量是每次读,写操作的序号,通过在 MainEnter 中添加两个成员变量 a1,a2,每次自加,在事件处理中将值操作参数,new Thread(new ReadWriteThread(W,a2+).start(),传递给读写线程。三 程序中用到的各个类第一个类:主执行类:package readerandwriter;import java.awt.event.ActionEvent;import java.awt.event.ActionListener;public class MainEnte
10、r implements ActionListener/* 主界面*/static MainFrame frame;/* 读写线程序号*/int a1,a2;public MainEnter()frame = new MainFrame(“信号量解决读者-写者问题“,this);frame.setVisible(true);Overridepublic void actionPerformed(ActionEvent e) if(e.getSource() = frame.buttonRead)new Thread(new ReadWriteThread(R,a1+).start();else
11、 if(e.getSource() = frame.buttonWrite)new Thread(new ReadWriteThread(W,a2+).start();else if(e.getSource() = frame.buttonPriority)if(frame.buttonPriority.getText() = “写优先“)ReadWriteThread.setPriority(2);frame.buttonPriority.setText(“读优先“);elseReadWriteThread.setPriority(1);frame.buttonPriority.setTex
12、t(“写优先“);public static void main(String args)new MainEnter();第二个类:界面类:/主界面package readerandwriter;import java.awt.Color;import java.awt.Dimension;import java.awt.Font;import java.awt.TextArea;import java.awt.Toolkit;import javax.swing.JButton;import javax.swing.JFrame;import javax.swing.JLabel;impor
13、t javax.swing.JPanel;import javax.swing.JTextField;public class MainFrame extends JFrame/* */private static final long serialVersionUID = -6171365492410371629L;/* 主面板*/JPanel panel;/* 读者和写者人数标签*/JLabel labelReader,labelWriter;/* 读者和写者人数 JTextField;*/JTextField textReader,textWriter;/* 读写按钮*/JButton
14、buttonRead,buttonWrite;/* 读写优先级按钮,读写优先标签*/JButton buttonPriority;JLabel labelPriority;/* 信息显示文本域*/TextArea textMessage;public MainFrame(String str,MainEnter mainEnter)super(str);this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);Font font = new Font(“宋体“,0,14);/设置主面板panel = new JPanel(null);panel.s
15、etBackground(Color.LIGHT_GRAY);/设置读写标签labelReader = new JLabel(“读者人数“);labelReader.setFont(font);labelWriter = new JLabel(“写者人数“);labelWriter.setFont(font);/读者和写者显示框textReader = new JTextField(“0“);textReader.setEditable(false);textWriter = new JTextField(“0“);textWriter.setEditable(false);/设置读写按钮bu
16、ttonRead = new JButton(“读操作“);buttonRead.setFont(font);buttonRead.addActionListener(mainEnter);buttonWrite = new JButton(“写操作“);buttonWrite.setFont(font);buttonWrite.addActionListener(mainEnter);/读写优先切换按钮, 读写优先标签buttonPriority = new JButton(“写优先“);buttonPriority.setFont(font);buttonPriority.addActio
17、nListener(mainEnter);labelPriority = new JLabel(“读写优先切换“);labelPriority.setFont(font);/显示文本域textMessage = new TextArea(20,20);textMessage.setEditable(false);/控件布局textMessage.setBounds(10, 10, 300, 200);labelReader.setBounds(320, 15, 100, 30);textReader.setBounds(340, 50, 40, 25);labelWriter.setBound
18、s(320, 100, 100, 30);textWriter.setBounds(340, 135, 40, 25);buttonRead.setBounds(60, 230, 80, 30);buttonWrite.setBounds(180, 230, 80, 30);labelPriority.setBounds(320, 200, 100, 25);buttonPriority.setBounds(320, 230, 80, 30);/控件添加panel.add(labelPriority);panel.add(buttonPriority);panel.add(labelReade
19、r);panel.add(labelWriter);panel.add(textReader);panel.add(textWriter);panel.add(textMessage);panel.add(buttonRead);panel.add(buttonWrite);add(panel);setSize(430,330);/在屏幕中央显示Dimension scr = Toolkit.getDefaultToolkit().getScreenSize();Dimension fra = this.getSize();if (fra.width scr.width) fra.width = scr.width;if (fra.height scr.height) fra.height = scr.height;this.setLocation(scr.width - fra.width) / 2,(scr.height - fra.height) / 2);第三个类:读写线程类:package readerandwriter;import java.util.Date;public class ReadWriteThread implements Runnable