操作系统——生产者消费者问题

生产者消费者问题是操作系统中非常重要的知识点。
其思想就是生产者和消费者公用一个缓冲区,生产者生产产品放入缓冲区,消费者从缓冲区取出产品,当缓冲区满,那么生产者阻塞,当缓冲区空,消费者阻塞,同时二者在放入和取出时应当独占缓冲区,即不允许对方操作缓冲区以保证同步。
在这类问题当中,一般至少需要维持三个变量:

  • 空余位置大小
  • 已占位置大小
  • 互斥锁

用代码实现

var items = 0, space = 10, mutex = 1;
item buf[n];

producer {
    while( true ) {
        wait( space );  // 等待缓冲区有空闲位置, 在使用PV操作时,条件变量需要在互斥锁之前
        wait( mutex );  // 保证在product时不会有其他线程访问缓冲区
        
        buf.push(item);
        
        signal( mutex );  // 唤醒的顺序可以不同
        signal( items );  // 通知consumer缓冲区有资源可以取走
    }
}

consumer {
    while( true ) {
        wait( items );  // 等待缓冲区有资源可以使用
        wait( mutex );  // 保证在consume时不会有其他线程访问缓冲区

        buf.pop();  // 将buf[out]位置的的资源取走

        signal( mutex );  // 唤醒的顺序可以不同
        signal( space );  // 通知缓冲区有空闲位置
    }
}

例题
桌子上只有一个盘子,每次只能向其中放入一个水果,爸爸只放苹果,女儿只吃苹果,妈妈只放橘子,儿子只吃橘子。只有盘子空时,妈妈或爸爸才可放一个水果;当盘子有自己需要的水果时,儿子或女儿才可以从盘子中取出。

semaphore plate=1,apple=0,orange=0;
dad()
{
	while(1)
	{
		wait(plate);
		put an apple;
		signal(apple);
	}
}
mom()
{
	while(1)
	{
		wait(plate);
		put an orange;
		signal(orange);
	}
}
daughter()
{
	while(1)
	{
		wait(orange);
		take an orange;
		signal(plate);
	}
}
son()
{
	while(1)
	{
		wait(apple);
		take an apple;
		signal(plate);
	}
}
  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一个基于Java的生产者消费者问题的代码实现,附带GUI界面: ```java import javax.swing.*; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.util.ArrayList; import java.util.List; public class ProducerConsumer extends JFrame implements ActionListener { private final int BUFFER_SIZE = 5; // 缓冲区大小 private final List<Integer> buffer = new ArrayList<>(BUFFER_SIZE); // 缓冲区 private final Object lock = new Object(); // 同步锁对象 private final JLabel bufferLabel = new JLabel(); // 显示缓冲区的标签 private final JTextField producerTextField = new JTextField(8); // 生产者输入框 private final JTextField consumerTextField = new JTextField(8); // 消费者输入框 private final JButton startButton = new JButton("开始"); // 开始按钮 private final JButton stopButton = new JButton("停止"); // 停止按钮 private Producer producer; private Consumer consumer; public ProducerConsumer() { setTitle("生产者消费者问题"); setSize(400, 200); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); JPanel panel = new JPanel(); panel.setLayout(new GridLayout(3, 2, 20, 10)); panel.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20)); panel.add(new JLabel("缓冲区:")); panel.add(bufferLabel); panel.add(new JLabel("生产者:")); panel.add(producerTextField); panel.add(new JLabel("消费者:")); panel.add(consumerTextField); startButton.addActionListener(this); stopButton.addActionListener(this); stopButton.setEnabled(false); panel.add(startButton); panel.add(stopButton); setContentPane(panel); setVisible(true); } @Override public void actionPerformed(ActionEvent e) { if (e.getSource() == startButton) { // 点击开始按钮时,启动生产者和消费者线程 producer = new Producer(); consumer = new Consumer(); producer.start(); consumer.start(); startButton.setEnabled(false); stopButton.setEnabled(true); } else if (e.getSource() == stopButton) { // 点击停止按钮时,停止生产者和消费者线程 producer.stopThread(); consumer.stopThread(); startButton.setEnabled(true); stopButton.setEnabled(false); } } private void updateBufferLabel() { // 更新缓冲区标签的显示 String bufferText = ""; for (Integer item : buffer) { bufferText += item + " "; } bufferLabel.setText(bufferText); } private class Producer extends Thread { private boolean stop = false; public void stopThread() { stop = true; } @Override public void run() { while (!stop) { synchronized (lock) { // 如果缓冲区已满,则等待 while (buffer.size() == BUFFER_SIZE) { try { lock.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } // 生产一个随机数,并添加到缓冲区 int item = (int) (Math.random() * 100); buffer.add(item); System.out.println("生产者生产了:" + item); updateBufferLabel(); // 唤醒一个等待的线程(可能是消费者) lock.notify(); } try { // 线程休眠一段时间,模拟生产过程 Thread.sleep((int) (Math.random() * 2000)); } catch (InterruptedException e) { e.printStackTrace(); } } } } private class Consumer extends Thread { private boolean stop = false; public void stopThread() { stop = true; } @Override public void run() { while (!stop) { synchronized (lock) { // 如果缓冲区为空,则等待 while (buffer.size() == 0) { try { lock.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } // 从缓冲区中取出一个元素,并消费它 int item = buffer.remove(buffer.size() - 1); System.out.println("消费者消费了:" + item); updateBufferLabel(); // 唤醒一个等待的线程(可能是生产者) lock.notify(); } try { // 线程休眠一段时间,模拟消费过程 Thread.sleep((int) (Math.random() * 2000)); } catch (InterruptedException e) { e.printStackTrace(); } } } } public static void main(String[] args) { new ProducerConsumer(); } } ``` 运行该程序,将会显示一个GUI界面,包括一个显示缓冲区的标签、两个输入框(分别用于生产者和消费者输入数据)、一个开始按钮和一个停止按钮。点击开始按钮,程序将启动一个生产者线程和一个消费者线程,并开始模拟生产者和消费者在缓冲区中的操作;点击停止按钮,程序将停止生产者和消费者线程,结束模拟过程。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值