java实现:《操作系统实验一》:模拟记录型信号量解决生产者-消费者问题

模拟记录型信号量解决生产者-消费者问题

作为java多线程的经典例题之一的生产者消费者问题。

  • 用记录型信号量解决生产者-消费者问题
  • 假定在生产者和消费者之间的公用缓冲池中具有n个缓冲区,
    这时可利用互斥信号量mutex实现诸进程对缓冲池的互斥使用;
    • 利用信号量empty和full分别表示缓冲池中空缓冲区和满缓冲
    区的数量。
    • 又假定这些生产者和消费者相互等效,只要缓冲池未满,生
    产者便可将消息送入缓冲池;
    • 只要缓冲池未空,消费者便可从缓冲池中取走一个消息。

参考代码:

int in = 0, out = 0;//in: 输入指针, out: 输出指针;
item buffer[n];//n个缓冲区组成的数组;
semaphore mutex = 1, full = 0, empty = n;
//mutex: 互斥信号量, 生产者进程和消费者进程都只能互斥访问缓冲区;
//full: 资源信号量, 满缓冲区的数量;
//empty: 资源信号量, 空缓冲区的数量;//信号量不允许直接参与运算, 故都要定义;

//生产者程序;
void Producer() {
  do {
      生产者生产一个产品nextp;
      wait(empty);//申请一个空缓冲区;
      wait(mutex);//申请临界资源;
      buffer[in] = nextp;//将产品添加到缓冲区;
      in = (in + 1) % n;//类似于循环队列;
      signal(mutex);//释放临界资源;
      signal(full);//释放一个满缓冲区;
  } while (TRUE);
}

//消费者程序;
void Producer() {
  do {
      wait(full);//申请一个满缓冲区;
      wait(mutex);//申请临界资源;
      nextc = buffer[out];//将产品从缓冲区取出;
      out = (out + 1) % n;//类似于循环队列;
      signal(mutex);//释放临界资源;
      signal(empty);//释放一个空缓冲区;
      消费者将一个产品nextc消费; 
 } while (TRUE);
}

java实现及解析;

public class Main {
	public static void main(String[] args) {
		Main main=new Main();
		Buffer[] buffers=new Buffer[bufferSize];
		//给缓冲区编号:
		for(int i=0;i<bufferSize;i++) {
			buffers[i]=main.new Buffer();
			buffers[i].setNumber(i+1);
		}
		
		Producer p=main.new Producer(buffers);
		p.start();
		Customer c=main.new Customer(buffers);
		c.start();
	}
	/**
	定义生产者,消费者共享的临界资源缓冲区的数量。
	Semaphore也是一个线程同步的辅助类,可以维护当前访问自身的线程个数,并提供了同步机制。它其中的常用方法:
	参数为许可证数量。
	void acquire():从此信号量获取一个许可,在提供一个许可前一直将线程阻塞,否则线程被中断。(相当于加锁)
  void release():释放一个许可,将其返回给信号量。(相当于释放锁)
  int availablePermits():返回此信号量中当前可用的许可数。
  boolean hasQueuedThreads():查询是否有线程正在等待获取。
	*/
	private static int bufferSize=20;//缓冲区数量
	private Semaphore mutex=new Semaphore(1);//互斥信号量
	//初始值为bufferSize个许可证,也就是说缓冲区一个东西也没有放
	private Semaphore empty=new Semaphore(bufferSize);//空缓冲区,
	private Semaphore full=new Semaphore(0);//满缓冲区
	int in=0,out=0;
	
	//定义wait信号方法:加锁
	public int WAIT(Semaphore semaphore) {
		try {
			semaphore.acquire();
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return semaphore.availablePermits();
	}
	//定义signal信号方法:释放锁
	public int SIGNAL(Semaphore semaphore) {
		semaphore.release();
		return semaphore.availablePermits();
	}
	
	/**
	 * 共享缓冲区
	 * */
	class Buffer{
		private int number;//缓冲区编号
		public int getNumber() {
			return number;
		}
		public void setNumber(int number) {
			this.number=number;
		}
		public void in() {
			System.out.println("放入第"+number+"号缓冲区");
		}
		
		public void out() {
			System.out.println("从第"+number+"号缓冲区拿出");
		}
	}
	
	/**
	 * 生产者
	 */
	class Producer extends Thread{
		Buffer[] buffers;
		public Producer(Buffer[] buffers) {
			this.buffers=buffers;
		}

		@Override
		public void run() {
			while(true) {
				WAIT(empty);
				WAIT(mutex);
				buffers[in].in();
				in=(in+1)%bufferSize;
				SIGNAL(mutex);
				SIGNAL(full);
			}
		}
	}
	/**
	 * 消费者
	 */
	class Customer extends Thread{
		Buffer[] buffers;
		public Customer(Buffer[] buffers) {
			this.buffers=buffers;
		}
		
		@Override
		public void run() {
			while(true) {
				WAIT(full);
				WAIT(mutex);
				buffers[out].out();
				out=(out+1)%bufferSize;
				SIGNAL(mutex);
				SIGNAL(empty);
			}
		}
	}
	
}

运行结果:
在这里插入图片描述

  • 6
    点赞
  • 42
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值