编程模拟生产者和消费者问题(java)
目录
一、实验目的和要求
二、实验环境
三、实验步骤
四、基本原理(思路):
代码:
一、实验目的和要求
模拟实现用同步机构避免发生进程执行时可能出现的与时间有关的错误。
进程是程序在一个数据集合上运行的过程,进程是并发执行的,也即系统中的多个进程轮流地占用处理器运行。
我们把若干个进程都能进行访问和修改的那些变量称为公共变量。由于进程是并发地执行的,所以,如果对进程访问公共变量不加限制,那么就会产生“与时间有关”的错误,即进程执行后所得到的结果与访问公共变量的时间有关。为了防止这类错误,系统必须要用同步机构来控制进程对公共变量的访问。一般说,同步机构是由若干条原语——同步原语——所组成。本实习要求学生模拟PV操作同步机构的实现,模拟进程的并发执行,了解进程并发执行时同步机构的作用。
二、实验环境
Windows操作系统和Visual C++6.0专业版或企业版
三、实验步骤
模拟PV操作同步机构,且用PV操作解决生产者——消费者问题。
(1) PV操作同步机构,由P操作原语和V操作原语组成,它们的定义如下:
P操作原语P (s):将信号量s减去1,若结果小于0,则执行原语的进程被置成等待信号量s的状态。
V操作原语V (s):将信号量s加1,若结果不大于0,则释放一个等待信号量s的进程。
(2) 生产者——消费者问题。
假定有一个生产者和一个消费者,生产者每次生产一件产品,并把生产的产品存入共享缓冲器以供消费者取走使用。消费者每次从缓冲器内取出一件产品去消费。禁止生产者将产品放入已满的缓冲器内,禁止消费者从空缓冲器内以产品。假定缓冲器内可同时存放10件产品。
(3) 进程控制块PCB。
为了记录进程执行时的情况,以及进程让出处理器后的状态,断点等信息,每个进程都有一个进程控制块PCB。在模拟实习中,假设进程控制块的结构如图3-1。其中进程的状态有:运行态、就绪态、等待态和完成态。当进程处于等待态时,在进程控制块PCB中要说明进程等待原因(在模拟实习中进程等待原因是为等待信号量s1或s2);当进程处于等待态或就绪态时,PCB中保留了断点信息,一旦进程再度占有处理器则就从断点位置继续运行;当进程处于完成状态,表示进程执行结束。
四、基本原理(思路):
生产者在缓冲区满后,进入休眠。直到消费者在缓冲区中消耗数据后,生产者才会被唤醒
消费者在缓冲区空后,进入休眠。直到生产者向缓冲区中添加数据后,消费者才会被唤醒
将curNum(缓冲区中的现有数据量),maxNum(缓冲区中最大数据量),lock(互斥锁)封装在静态mutex类中
每次生产者生产一次或者消费者消费一次,唤醒其他所有线程
代码:
public class Appale {static class mutex {public static int curNum = 0;//苹果数量,初始值为 0public static int maxNum = 10;//最大容量,初始值为 10public static Object lock = new Object();//一个对象,用作同步锁}//生产者线程static class Producer extends Thread {public void run() {//重写run()方法while (true) {synchronized (mutex.lock) {//synchronized确保同一时间只有一个线程可以执行该代码块。try {Thread.sleep(100);//让当前线程睡眠100 毫秒,模拟生产过程中的延迟} catch (InterruptedException e) {e.printStackTrace();}while (mutex.curNum == 0) {//如果物品栏为空System.out.println("物品栏已空,开始生产");try {mutex.lock.wait();//使当前线程等待,释放锁,并让出 CPU 时间片。} catch (InterruptedException e) {e.printStackTrace();}}mutex.curNum --;System.out.println("消费了一个苹果...物品栏中还剩下" + mutex.curNum + "个苹果");mutex.lock.notifyAll();//唤醒所有等待在该锁上的线程。}}}}//消费者进程static class Consumer extends Thread {public void run() {//重写run()方法while (true) {synchronized (mutex.lock) {//同步锁try {Thread.sleep(100);} catch (InterruptedException e) {e.printStackTrace();}while (mutex.curNum >= mutex.maxNum) {//如果物品栏已满System.out.println("物品栏已满,开始消费");try {mutex.lock.wait();//使当前线程等待,释放锁,并让出 CPU 时间片。} catch (InterruptedException e) {e.printStackTrace();}}mutex.curNum ++;System.out.println("生产了一个苹果...物品栏中有" + mutex.curNum + "个苹果");mutex.lock.notifyAll();//唤醒所有等待在该锁上的线程。}}}}public static void main(String[] args) {Producer producer = new Producer();Consumer consumer = new Consumer();producer.start();//启动生产者进程,调用run()方法consumer.start();}
}