生产者-消费者 实验模型
? 1、复现因竞争导致错误的生产者-消费者问题
生产者的主要作用是生成一定量的数据放到缓冲区中,然后重复此过程。与此同时,消费者也在缓冲区消耗这些数据。该问题的关键就是要保证生产者不会在缓冲区满时加入数据,消费者也不会在缓冲区中空时消耗数据。
要解决该问题,就必须让生产者在缓冲区满时休眠(要么干脆就放弃数据),等到下次消费者消耗缓冲区中的数据的时候,生产者才能被唤醒,开始往缓冲区添加数据。同样,也可以让消费者在缓冲区空时进入休眠,等到生产者往缓冲区添加数据之后,再唤醒消费者。通常采用进程间通信的方法解决该问题。如果解决方法不够完善,则容易出现死锁的情况。出现死锁时,两个线程都会陷入休眠,等待对方唤醒自己。
当对临界资源的使用放弃锁的保护会出现的结果: 会导致对临界资源的重复占用,共享数据不再安全。
不添加同步锁,当两个(多个)线程共同使用一个共享资源时,会出现资源的抢占,对于每个进程而言,抢占某个特定的资源,所获得的结果是不确定的。
package Question04; /***
* 将同步锁去掉的后果 */
public class Main {
public static void main(String[] args) { }
private static int bufferSize=20;//缓冲区数量 int in=0,out=0;
Main main=new Main();
Buffer[] buffers=new Buffer[bufferSize]; //给缓冲区编号:
for(int i=0;i Producer p=main.new Producer(buffers); p.start(); Customer c=main.new Customer(buffers); c.start(); buffers[i]=main.new Buffer(); buffers[i].setNumber(i+1); class Buffer{ } /** * 生产者 */ class Producer extends Thread{ } /** * 消费者 */ class Customer extends Thread{ Buffer[] buffers; public Customer(Buffer[] buffers) { } @Override this.buffers=buffers; Buffer[] buffers; public Producer(Buffer[] buffers) { } @Override public void run() { } while(true) { } buffers[in].in(); in=(in+1)%bufferSize; this.buffers=buffers; private int number;//缓冲区编号 public int getNumber() { } public void setNumber(int number) { } public void in() { } public void out() { } System.out.println(\从第\+number+\号缓冲区拿出\); System.out.println(\放入第\+number+\号缓冲区\); this.number=number; return number; } } public void run() { } while(true) { } buffers[out].out(); out=(out+1)%bufferSize; 运行结果: ? 2、模拟记录型信号量解决生产者-消费者问题 Java代码: package Question01; import java.util.concurrent.Semaphore; /*** * 用记录型信号量解决生产者-消费者问题 * 假定在生产者和消费者之间的公用缓冲池中具有n个缓冲区, 这时可利用互斥信号量mutex实现诸进程对缓冲池的互斥使用; 利用信号量empty和full分别表示缓冲池中空缓冲区和满缓冲 区的数量。 又假定这些生产者和消费者相互等效,只要缓冲池未满,生 产者便可将消息送入缓冲池; 只要缓冲池未空,消费者便可从缓冲池中取走一个消息。 */ public class Main { public static void main(String[] args) { } private static int bufferSize=20;//缓冲区数量 private Semaphore mutex=new Semaphore(1);//互斥信号量 private Semaphore empty=new Semaphore(bufferSize);//空缓冲区 private Semaphore full=new Semaphore(0);//满缓冲区 int in=0,out=0; //定义wait信号方法:加锁 public int WAIT(Semaphore semaphore) { } try { } return semaphore.availablePermits(); semaphore.acquire(); // TODO Auto-generated catch block e.printStackTrace(); } catch (InterruptedException e) { Main main=new Main(); Buffer[] buffers=new Buffer[bufferSize]; //给缓冲区编号: for(int i=0;i Producer p=main.new Producer(buffers); p.start(); Customer c=main.new Customer(buffers); c.start(); buffers[i]=main.new Buffer(); buffers[i].setNumber(i+1); //定义signal信号方法:释放锁 public int SIGNAL(Semaphore semaphore) { } /** * 共享缓冲区 * */ class Buffer{ } /** * 生产者 */ class Producer extends Thread{ Buffer[] buffers; public Producer(Buffer[] buffers) { } @Override public void run() { while(true) { } WAIT(empty); WAIT(mutex); buffers[in].in(); in=(in+1)%bufferSize; SIGNAL(mutex); SIGNAL(full); this.buffers=buffers; private int number;//缓冲区编号 public int getNumber() { } public void setNumber(int number) { } public void in() { } public void out() { } System.out.println(\从第\+number+\号缓冲区拿出\); System.out.println(\放入第\+number+\号缓冲区\); this.number=number; return number; semaphore.release(); return semaphore.availablePermits();