写优先的读者写者问题(Java实现)

该题系吉林大学19级软件学院操作系统课设题之一

 

 

先输入初始时的写者读者情况,优先级顺序做了随机处理

 

代码如下

GUI:


import javax.swing.*;
import javax.swing.border.Border;
import javax.swing.text.BadLocationException;
import javax.swing.text.SimpleAttributeSet;
import javax.swing.text.StyleConstants;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.LinkedList;
import java.util.concurrent.Semaphore;

public class ReadAndWrite extends JFrame {
    public static Semaphore rw = new Semaphore(1);
    public static Semaphore mutex = new Semaphore(1);
    public static Semaphore w = new Semaphore(1);
    public static Semaphore fresh = new Semaphore(1);
    public static int count = 0;

    public static LinkedList<String> Re = new LinkedList<String>();//读空间
    public static LinkedList<String> Wr = new LinkedList<String>();//写空间
    public static LinkedList<String> ing = new LinkedList<String>();//正在的状态



    private int reader = 0;//写者数量和编号记录
    private int writer = 0;//读者数量和编号记录

    //三个大的文本区域
    static JTextPane jTextPane1 = new JTextPane();//读
    static JTextPane jTextPane2 = new JTextPane();//文件
    static JTextPane jTextPane3 = new JTextPane();//写




    ReadAndWrite(int a, int b){
        super("写优先的读者写者问题");
        reader = a+1;
        writer = b+1;
        for(int i = 1;i<=a;i++)
            new Thread(new Read(i)).start();
        for(int i = 1;i<=b;i++)
            new Thread(new Write(i)).start();

        setBounds(400,300,600,500);


        JPanel jPanel1 = new JPanel(new BorderLayout());//读
        JPanel jPanel2 = new JPanel(new BorderLayout());//临界区
        JPanel jPanel3 = new JPanel(new BorderLayout());//写
        jPanel1.setBackground(Color.CYAN);
        jPanel2.setBackground(Color.PINK);
        jPanel3.setBackground(Color.CYAN);


        this.add(jPanel1,BorderLayout.WEST);
        this.add(jPanel2,BorderLayout.CENTER);
        this.add(jPanel3,BorderLayout.EAST);

        JLabel label1 = new JLabel("       读者       ");
        JLabel label2 = new JLabel("        临界区");
        JLabel label3 = new JLabel("       写者       ");
        label1.setFont(new Font("宋体",Font.BOLD,20));
        label2.setFont(new Font("宋体",Font.BOLD,20));
        label3.setFont(new Font("宋体",Font.BOLD,20));

        jPanel1.add(label1,BorderLayout.NORTH);
        jPanel2.add(label2,BorderLayout.NORTH);
        jPanel3.add(label3,BorderLayout.NORTH);

        jTextPane2.setLayout(new FlowLayout(FlowLayout.CENTER));//没起作用
        jTextPane1.setEditable(false);//禁止编辑
        jTextPane2.setEditable(false);
        jTextPane3.setEditable(false);

        //三个大的文本区域
        jTextPane1.setFont(new Font("宋体",Font.BOLD,16));
        jTextPane2.setFont(new Font("宋体",Font.BOLD,16));
        jTextPane3.setFont(new Font("宋体",Font.BOLD,16));


        jPanel1.add(new JScrollPane(jTextPane1),BorderLayout.CENTER);
        jPanel2.add(new JScrollPane(jTextPane2),BorderLayout.CENTER);
        jPanel3.add(new JScrollPane(jTextPane3),BorderLayout.CENTER);




        JButton jButton1 = new JButton("加入读者");
        JButton jButton2 = new JButton("加入写者");
        jButton1.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                new Thread(new Read(reader)).start();
                reader++;
            }
        });
        jButton2.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                new Thread(new Write(writer)).start();
                writer++;
            }
        });

        jPanel1.add(jButton1,BorderLayout.SOUTH);
        jPanel3.add(jButton2,BorderLayout.SOUTH);

        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setVisible(true);

    }

    public static void insert1(String str)//读模块的gui部分
    {
        SimpleAttributeSet set = new SimpleAttributeSet();
        StyleConstants.setUnderline(set, true);
        try
        {
            jTextPane1.getDocument().insertString(jTextPane1.getDocument().getLength(), str + "\n", set);
        }
        catch (BadLocationException e)
        {
            e.printStackTrace();
        }
    }
    public static void insert2(String str)//被访问文件模块的gui部分
    {
        SimpleAttributeSet set = new SimpleAttributeSet();
        StyleConstants.setUnderline(set, true);
        try
        {
            jTextPane2.getDocument().insertString(jTextPane2.getDocument().getLength(), str + "\n", set);
        }
        catch (BadLocationException e)
        {
            e.printStackTrace();
        }
    }
    public static void insert3(String str)//写模块的gui部分
    {
        SimpleAttributeSet set = new SimpleAttributeSet();
        StyleConstants.setUnderline(set, true);
        try
        {
            jTextPane3.getDocument().insertString(jTextPane3.getDocument().getLength(), str + "\n", set);
        }
        catch (BadLocationException e)
        {
            e.printStackTrace();
        }
    }

    public static void refresh()
    {
        jTextPane1.setText(null);
        jTextPane2.setText(null);
        jTextPane3.setText(null);


        for(String a : Re)
        {
            insert1("读者"+a);
        }
        for(String b : ing)
        {
            insert2(b);
        }
        for(String c : Wr)
        {
            insert3("写者"+c);
        }

    }







    public static void main(String[] args)
    {
        int a = Integer.parseInt(JOptionPane.showInputDialog("请输入初始读者数量"));
        int b = Integer.parseInt(JOptionPane.showInputDialog("请输入初始写者数量"));
        new ReadAndWrite(a,b);
//        new Thread(new Read(1)).start();
//        new Thread(new Read(2)).start();
//        new Thread(new Read(3)).start();
//        new Thread(new Write(1)).start();
//        new Thread(new Write(2)).start();
    }
}

写者

import java.util.concurrent.Semaphore;

import java.util.Random;

public class Read extends Thread{
    private int num;
    Read(int num)
    {
        this.num = num;
    }

    public void run() {
        try {
                synchronized(this)
                {
                    Random random = new Random();
                    wait(random.nextInt(500));
                    ReadAndWrite.insert1("读者"+num+"打算读文件");

                    ReadAndWrite.Re.add(num+"打算读文件");

                    ReadAndWrite.w.acquire();           //实现写有先
                    ReadAndWrite.mutex.acquire();       //防止读者之间同步访问count,读者互斥访问count
                    if(ReadAndWrite.count==0)
                        ReadAndWrite.rw.acquire();      //实现读写互斥
                    ReadAndWrite.count++;               //我只要有东西正在读你,你就不许给我写东西,实现多读者同步的关键
                    ReadAndWrite.mutex.release();
                    ReadAndWrite.w.release();

                    //以下为读文件的阶段
                    ReadAndWrite.insert2("读者"+num+"正在读文件");
                    ReadAndWrite.ing.add("读者"+num+"正在读文件");
                    wait(random.nextInt(5000)+1500);
                    ReadAndWrite.insert2("读者"+num+"结束读文件");
                    ReadAndWrite.insert1("读者"+num+"完成读文件");
                    ReadAndWrite.ing.remove("读者"+num+"正在读文件");
                    ReadAndWrite.Re.remove(num+"打算读文件");
                    //以上为读文件的阶段

                    wait(3000);
                    ReadAndWrite.fresh.acquire();              //实现刷新页面时,线程的互斥
                    ReadAndWrite.refresh();                    //刷新页面,通过队列的信息刷新页面
                    ReadAndWrite.fresh.release();

                    ReadAndWrite.mutex.acquire();
                    ReadAndWrite.count--;                   //文件读完了,读完一个出来一个,count--了
                    if(ReadAndWrite.count==0)
                        ReadAndWrite.rw.release();
                    ReadAndWrite.mutex.release();
                }

        } catch (InterruptedException e) {
            System.out.println("读者"+num+"出现错误!");
            e.printStackTrace();
        }
    }

}

读者

import java.util.Random;

public class Write extends Thread
{
    private int num;
    Write(int num)
    {
        this.num = num;
    }

    public void run()
    {
        try
        {
                synchronized(this)
                {
                    Random random = new Random();
                    wait(random.nextInt(500));
                    ReadAndWrite.insert3("写者"+num+"打算写文件");
                    ReadAndWrite.Wr.add(num+"打算写文件");
                    ReadAndWrite.w.acquire();
                    ReadAndWrite.rw.acquire();
                    ReadAndWrite.insert2("写者"+num+"正在写文件");
                    ReadAndWrite.ing.add("写者"+num+"正在写文件");
                    wait(random.nextInt(10000)+3000);
                    ReadAndWrite.insert2("写者"+num+"结束写文件");

                    ReadAndWrite.insert3("写者"+num+"完成写文件");
                    ReadAndWrite.ing.remove("写者"+num+"正在写文件");
                    ReadAndWrite.Wr.remove(num+"打算写文件");

                    wait(3000);
                    ReadAndWrite.fresh.acquire();
                    ReadAndWrite.refresh();//刷新页面,通过队列的信息刷新页面
                    ReadAndWrite.fresh.release();

                    ReadAndWrite.rw.release();
                    ReadAndWrite.w.release();
                }
        } catch (InterruptedException e)
        {
            System.out.println("写者"+num+"出现错误!");
            e.printStackTrace();
        }

    }
}

环境:IDEA

 

  • 5
    点赞
  • 34
    收藏
    觉得还不错? 一键收藏
  • 7
    评论
读者写者问题是一个经典的同步问题,用于说明多进程/线程之间的协作和竞争关系。问题的场景是这样的:有一篇文章需要被多个读者同时读取,但是只能被一个写者修改,当一个写者正在修改文章时,其他读者写者都必须等待。同时,读者可以同时访问文章,但是写者和其他写者读者都不可以同时修改或访问文章。这个问题的解决方案需要考虑到以下几个问题: 1. 如何实现读者写者之间的互斥? 2. 如何避免写者饥饿(即写者无法获取到资源)? 3. 如何避免读者饥饿(即读者无法获取到资源)? 解决该问题的一种常见的解决方案是使用信号量或者互斥锁来控制读者写者之间的互斥。使用一个计数器来记录当前读者的数量,当第一个读者访问文章时,它会获取一个共享锁,其他读者也可以获取共享锁,同时写者会等待共享锁被释放。当一个写者需要修改文章时,它会获取一个独占锁,其他读者写者都必须等待该锁被释放。这样可以保证读者写者之间的互斥。为了避免写者饥饿,可以使用一个队列来保证写者读者之间的公平性,即写者等待的时间不会太长。为了避免读者饥饿,可以使用一个计数器来记录当前等待的写者数量,当读者释放共享锁时,如果有等待的写者,将优先写者获取锁。 当然,实现读者写者问题还有其他的解决方案,例如使用条件变量等,但是无论使用哪种方案,都需要保证读者写者之间的互斥和公平性,避免饥饿现象的发生。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值