用信号量解决生产者消费者问题实验报告
一、实验目的:
通过信号量这一机制,解决生产者消费者问题中的两个进程会同时睡眠的问题。然后在实验中 ,设置多个生产者和消费者线程,设置一块大小为100的缓存,实现生产者消费者交替访问缓存的问题。
二、实验过程:
1. 我在实验中使用的是Java 语言,Java 语言中有自带的信号量Semaphore ,其中的acquire()方法相当于down(),其中的release()方法相当于up()。利用Java 自带的这个类便可以按照书中给的方法解决生产者消费者的问题。
2. 在实验中,我设置了3个类,分别为生产者线程类,消费者线程类,仓库类。生产者和消费者类都是继承了Runnable 类,生产者的run()方法就是不断往仓库放物品(),消费者的run()方法就是不断从仓库拿物品。 class Producer implements Runnable
{
int num=0; @Override public void run() {
while(true)
{ num++; try {
buffer.put(num);
System.out.println("生产数字"+num); Thread.sleep(10); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace();
}
} } }
class Consumer implements Runnable { @Override public void run() { // TODO Auto-generated method stub while(true) { try { int num=(int)buffer.take(); System.out.println("消费者拿出数字"+num); Thread.sleep(1000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } } } }
3. 然后仓库类其实就是带了full 、empty 、mutex 这3个信号量的buffer 数组,然后再
这个类中有两个方法:put(),take()。put()方法就是书中所写的produce()方法,take()方法就是书中所写的consumer()方法。在方法中使用信号量来保证生产者和消费者在放入库存和拿出库存时不会起冲突也不会双方都睡着。
/*
* 生产者生产并放入库存 */ public void put(Object o)throws InterruptedException { //保证非空, 将空槽数目-1 empty.acquire(); if(!empty.tryAcquire()) { System.out.println("仓库已满,稍后再生产"); } //得到写库存的权利 mutex.acquire(); try{ items[putindex]=o; putindex++; if(putindex==items.length) {
/*
} putindex=0; } count++; }finally { mutex.release(); //将满槽数目+1 full.release(); } * 消费者拿出库存 */ public Object take()throws InterruptedException { //将满槽数目-1 full.acquire(); if(!full.tryAcquire()) { System.out.println("仓库已空,稍后再消费"); } //拿到库存 mutex.acquire(); try{ Object o=items[takeindex]; takeindex++; if(takeindex==items.length) { takeindex=0; } count--; return o; }finally { mutex.release(); //给空槽+1 empty.release(); } }
4. 在main()函数中新建生产者和消费者线程,然后开始运行即可看到结果。
三、实验结果:
在此结果中,主要就是这4张图代表的状态。图1表示在运行初始时,仓库为空,所以一直提醒消费者,仓库已空,稍候消费,然后阻塞消费者。图2表示多个生产者进程一直在生产放入库存,直到仓库已满。图3表示仓库几乎为满的情况下,消费者不停消费拿出库存,然后提示生产者仓库已满,稍候再放。图4就是一个生产消费几乎
达到平衡的状态。
图1图
2
图3 图4
用信号量解决生产者消费者问题实验报告
一、实验目的:
通过信号量这一机制,解决生产者消费者问题中的两个进程会同时睡眠的问题。然后在实验中 ,设置多个生产者和消费者线程,设置一块大小为100的缓存,实现生产者消费者交替访问缓存的问题。
二、实验过程:
1. 我在实验中使用的是Java 语言,Java 语言中有自带的信号量Semaphore ,其中的acquire()方法相当于down(),其中的release()方法相当于up()。利用Java 自带的这个类便可以按照书中给的方法解决生产者消费者的问题。
2. 在实验中,我设置了3个类,分别为生产者线程类,消费者线程类,仓库类。生产者和消费者类都是继承了Runnable 类,生产者的run()方法就是不断往仓库放物品(),消费者的run()方法就是不断从仓库拿物品。 class Producer implements Runnable
{
int num=0; @Override public void run() {
while(true)
{ num++; try {
buffer.put(num);
System.out.println("生产数字"+num); Thread.sleep(10); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace();
}
} } }
class Consumer implements Runnable { @Override public void run() { // TODO Auto-generated method stub while(true) { try { int num=(int)buffer.take(); System.out.println("消费者拿出数字"+num); Thread.sleep(1000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } } } }
3. 然后仓库类其实就是带了full 、empty 、mutex 这3个信号量的buffer 数组,然后再
这个类中有两个方法:put(),take()。put()方法就是书中所写的produce()方法,take()方法就是书中所写的consumer()方法。在方法中使用信号量来保证生产者和消费者在放入库存和拿出库存时不会起冲突也不会双方都睡着。
/*
* 生产者生产并放入库存 */ public void put(Object o)throws InterruptedException { //保证非空, 将空槽数目-1 empty.acquire(); if(!empty.tryAcquire()) { System.out.println("仓库已满,稍后再生产"); } //得到写库存的权利 mutex.acquire(); try{ items[putindex]=o; putindex++; if(putindex==items.length) {
/*
} putindex=0; } count++; }finally { mutex.release(); //将满槽数目+1 full.release(); } * 消费者拿出库存 */ public Object take()throws InterruptedException { //将满槽数目-1 full.acquire(); if(!full.tryAcquire()) { System.out.println("仓库已空,稍后再消费"); } //拿到库存 mutex.acquire(); try{ Object o=items[takeindex]; takeindex++; if(takeindex==items.length) { takeindex=0; } count--; return o; }finally { mutex.release(); //给空槽+1 empty.release(); } }
4. 在main()函数中新建生产者和消费者线程,然后开始运行即可看到结果。
三、实验结果:
在此结果中,主要就是这4张图代表的状态。图1表示在运行初始时,仓库为空,所以一直提醒消费者,仓库已空,稍候消费,然后阻塞消费者。图2表示多个生产者进程一直在生产放入库存,直到仓库已满。图3表示仓库几乎为满的情况下,消费者不停消费拿出库存,然后提示生产者仓库已满,稍候再放。图4就是一个生产消费几乎
达到平衡的状态。
图1图
2
图3 图4