基于信号量与P/V操作同步机制的读者/写者问题的设计与实现 (写者优先)

在操作系统课程设计中,老师给了这样一个题目,并且要求以GUI的形式模拟整个操作过程。所以,首先映入我脑海的语言便是JAVA。主意敲定,开始构思,如何用JAVA来巧妙地表现这种机制,尽管Java提供了synchronized,Semaphore等关键词,但在构思过程中依然是困难的。

  建立读者类和写者类,建立之后为了实现写者优先需设定五个信号量,然而这五个信号量是在两个类中交替出现的,而且要保证原子性。不得已将这五个类全部放在主类中,设为静态变量。由此在另外两个类应用时很繁琐。

五个信号量:

public static Semaphore readCountSemaphore=new Semaphore(1); //读者数量更改,保持原子性

public static Semaphore writeSemaphore=new Semaphore(1);     //写者信号量
public static Semaphore reader_wait=new Semaphore(1); //读者信号量
public static Semaphore first_reader_wait=new Semaphore(1);//第一个读者,为了实现写者优先
public static Semaphore writerCountSemaphore=new Semaphore(1);//写者数量更改,保持原子性

完整代码:

主类:
package com;

import java.awt.BorderLayout;
import java.util.Random;
import java.util.Scanner;
import java.util.concurrent.Semaphore;

import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.JTextPane;
import javax.swing.text.BadLocationException;
import javax.swing.text.SimpleAttributeSet;
import javax.swing.text.StyleConstants;

public class ReadAndWrite extends JFrame
{
	public static int countReader;  //手动设置读者数
	public static int countWriter;  //手动设置写者数
	public static 	int readCount=0;  //等待读者数量
	public static   int writeCount=0; //等待写者数量
	public static Semaphore readCountSemaphore=new Semaphore(1); //读者数量更改,保持原子性
	public static Semaphore writeSemaphore=new Semaphore(1);     //写者信号量
	public static Semaphore  reader_wait=new Semaphore(1); //读者信号量
	public static Semaphore  first_reader_wait=new Semaphore(1);//第一个读者,为了实现写者优先
	public static Semaphore  writerCountSemaphore=new Semaphore(1);//写者数量更改,保持原子性
	
	//GUI
	static JTextField textfield1, textfield2, textfield3,textfield4;
	JPanel panel, panel1, panel2;
	JLabel label1, label2, label3, label4;
	static JTextPane textpane;
	public ReadAndWrite(){
		Scanner sc = new Scanner(System.in);//用来输入读写者个数
		System.out.println("读者个数:");
		countReader = sc.nextInt();
		System.out.println("写者个数:");
		countWriter = sc.nextInt();

		textpane = new JTextPane();//动态执行界面
		label1 = new JLabel("书:");
		label2 = new JLabel("等待读者个数:");
		label3 = new JLabel("等待写者个数:");
		textfield1 = new JTextField(10);//显示谁正在对数据操作
		textfield2 = new JTextField(10);//显示剩余读者个数
		textfield3 = new JTextField(10);//显示剩余写者个数
		panel1 = new JPanel();
		panel1.add(label1);
		panel1.add(textfield1);
		panel1.add(label2);
		panel1.add(textfield2);
		panel1.add(label3);
		panel1.add(textfield3);
		
		JLabel label4 = new JLabel("正在等待读写者:");
		textfield4 = new JTextField(44);//显示读写者的先后顺序
		panel2 = new JPanel();
		panel2.add(label4);
		panel2.add(textfield4);
		
		panel = new JPanel(new BorderLayout());
		panel.add(panel1,BorderLayout.NORTH);
		panel.add(panel2,BorderLayout.SOUTH);
		panel.add(new JScrollPane(textpane),BorderLayout.CENTER);
		setTitle("读写者问题");//将此窗体的标题设置为指定的字符串
		setBounds(300, 300, 600, 400);
		this.add(panel);
		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		this.setVisible(true);
		this.setResizable(false);
		
	}
	
	public static void insert(String str)//向textpane中插入动态信息
	{
		SimpleAttributeSet set = new SimpleAttributeSet();
		StyleConstants.setUnderline(set, true);
		try
		{
			textpane.getDocument().insertString(textpane.getDocument().getLength(), str + "\n", set);
		}
		catch (BadLocationException e)
		{
			e.printStackTrace();
		}
	}
	
	
	/**
	 * @param args
	 */
	public static void main(String[] args)
	{
		// TODO Auto-generated method stub
		ReadAndWrite raw = new ReadAndWrite();
		int i = 1;
		int j = 1;
		while(i<=ReadAndWrite.countReader||j<=ReadAndWrite.countWriter){
        	if(new Random().nextBoolean()){         //随机判断读写者
        		if(i>ReadAndWrite.countReader)
        			continue;
        		ReadAndWrite.insert("读者R"+i+"来了");
        		raw.textfield4.setText(raw.textfield4.getText()+"R"+i+",");
        		new ReadThread(i);
        		i++;
        	}
        	else{
        		if(j>ReadAndWrite.countWriter)
        			continue;
        		ReadAndWrite.insert("读者W"+j+"来了");
        		raw.textfield4.setText(raw.textfield4.getText()+"W"+j+",");
				new WriteThread(j);
				j++;
			}
		}
     }
}
读者类:
package com;

import java.util.Random;
//import java.util.concurrent.Semaphore;

public class ReadThread extends Thread
{
	public int id;
	public ReadThread(int id)
	{
		this.id = id;
		this.start();
	}

	public void run()
	{
		try{
			synchronized(this){
			if(ReadAndWrite.writeSemaphore.availablePermits()>0)//判断是否有写者正在操作
				ReadAndWrite.insert("读者R"+id+"可以读");
			else
				ReadAndWrite.insert("有写者在写操作,读者R"+id+"等待读");
			ReadAndWrite.reader_wait.acquire();//阻塞第一个之后的读者
			ReadAndWrite.first_reader_wait.acquire();//第一个读者申请资源,为了写者优先
			ReadAndWrite.readCountSemaphore.acquire();//保持writeCount的原子性
				if(ReadAndWrite.readCount==0)
						ReadAndWrite.writeSemaphore.acquire();
			ReadAndWrite.readCount++;
			ReadAndWrite.textfield2.setText(" "+ReadAndWrite.readCount);//GUI显示
			ReadAndWrite.readCountSemaphore.release();
			ReadAndWrite.first_reader_wait.release();
			ReadAndWrite.reader_wait.release();
			
			ReadAndWrite.insert("R"+id+"读文件");//GUI显示
			ReadAndWrite.textfield1.setText("读者R"+id);
			
			Thread.sleep((long) (new Random().nextFloat()*2000));
			ReadAndWrite.insert("读者R"+id+"读完了");
			ReadAndWrite.readCountSemaphore.acquire();
			ReadAndWrite.readCount--;
			ReadAndWrite.textfield2.setText(" "+ReadAndWrite.readCount);
				if(ReadAndWrite.readCount==0)
					ReadAndWrite.writeSemaphore.release();
			ReadAndWrite.readCountSemaphore.release();
			}
			
		}
		catch (InterruptedException e)
		{
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}
写者类:
package com;

import java.util.Random;
public class WriteThread extends Thread
{
		public int id;
		public WriteThread(int id)
		{
			this.id=id;
			this.start();
		}
		public void run()
		{
			try{
				synchronized(this){
					if(ReadAndWrite.writeSemaphore.availablePermits()>0)//判断是否有写者正在操作
						ReadAndWrite.insert("写者W"+this.id+"可以写");
					else
						ReadAndWrite.insert("写者W"+this.id+"不可以写");
			   ReadAndWrite.writerCountSemaphore.acquire();//保持writeCount的原子性
			   		if(ReadAndWrite.writeCount==0)
			   			ReadAndWrite.first_reader_wait.acquire();	//如果写者数量为0,第一个读者申请访问
			   ReadAndWrite.writeCount++;
			   ReadAndWrite.textfield3.setText(" "+ReadAndWrite.writeCount);//GUI显示
			   ReadAndWrite.writerCountSemaphore.release();
			   ReadAndWrite.writeSemaphore.acquire();//写者开始操作,与其他操作互斥
			   
			   ReadAndWrite.insert("写者W"+this.id+"正在写");//GUI显示
			   ReadAndWrite.textfield1.setText("写者W"+id);
			   
			   Thread.sleep((long) (new Random().nextFloat()*2000));
			   ReadAndWrite.insert("写者W"+this.id+"写完了");
			   ReadAndWrite.writeSemaphore.release();
			   ReadAndWrite.writerCountSemaphore.acquire();
			   ReadAndWrite.writeCount--;
			   ReadAndWrite.textfield3.setText(" "+ReadAndWrite.writeCount);
			   		if(ReadAndWrite.writeCount==0)//如果写者数量为0,唤醒第一个等待的读者
			   			ReadAndWrite.first_reader_wait.release();
			   ReadAndWrite.writerCountSemaphore.release();
		  }
	}
	catch (InterruptedException e)
	{
		// TODO Auto-generated catch block
		e.printStackTrace();
	}
   }
}


PS:这是第一次在CSDN记录我自己编程的过程,自知写的蹩脚的很,既然迈出了这一步,就等着接受唾沫。雄关漫道真如铁,走你!


posted @ 2015-09-19 14:46  鲨鱼辣椒TP  阅读(1343)  评论(0编辑  收藏  举报