生产者消费者问题

  1. 临界区:对临界资源进行访问的那段代码称为临界区。为了互斥访问临界资源,每个进程在进入临界区之前,需要先进行检查。
  2. 同步与互斥:
    同步:多个进程因为合作产生的直接制约关系,使得进程有一定的先后执行关系。
    互斥:多个进程在同一时刻只有一个进程能进入临界区。

使用信号量实现生产者消费者问题

  1. 使用一个容器来存放物品,只有当容器中还有空位置时,生产者才可以生产商品;只有当容器中物品数量大于0时,消费者才可以消费商品。
  2. 容器属于临界资源,所以需要使用一个互斥量mutex来控制对容器的互斥访问
  3. 为了同步生产者和消费者的行为,需要记录容器中物品的数量。数量可以使用信号量进行统计,这里需要使用两个信号量:empty和full。
    • empty表示容器中可供放入物品的数量即空位置的数量,只有empty>0时,生产者才可以生产
    • full表示容器中现存物品的数量,即可供消费者消费的物品的数量,只有full>0时,消费者才可以消费
  4. 注意:不能先对临界区加锁,再测试信号量。如果这么做了,那么可能会出现这种情况:生产者先对临界区加锁,然后对empty执行减1操作,此时empty变为0,那么生产者进入等待状态;消费者此时不能访问临界区,因为生产者对其加锁了,所以消费者不能执行empty+1操作,那么empty永远为0,导致生产者永远等待,不会释放锁,消费者因此也会永远等待下去。
class Cache {
	private int cacheSize=0;
	public Semaphore mutex;
	public Semaphore full;//容器已装满的时候,full<=0,生产者需要等待
	public Semaphore empty;//容器为空的时候,empty<=0,消费者需要等待
	public Cache(int size) {
		mutex=new Semaphore(1);//互斥量mutex来控制对缓冲区的互斥访问,通过0值来进行阻塞和唤醒
	    empty=new Semaphore(size);//容器中可供放入物品的数量即空位置的数量
	    full=new Semaphore(0);//容器中现存物品的数量,即可供消费的物品的数量
	}
	public int getCacheSize() {
		return cacheSize;
	}
	public void produce() throws InterruptedException {
		empty.acquire();//empty减1 减少了一个空位
		mutex.acquire();
		cacheSize++;
		System.out.println(Thread.currentThread().getName()+"生产了一个商品,当前商品的数量为:"+cacheSize);
		mutex.release();
		full.release();//full+1 增加了一个商品
	}
	public void consume() throws InterruptedException {
		full.acquire();//减少一件商品
		mutex.acquire();
		cacheSize--;
		System.out.println(Thread.currentThread().getName()+"消费了一个商品,当前商品的数量为:"+cacheSize);
		mutex.release();
		empty.release();//空位数量+1
	}
}
class Consumer implements Runnable{
	private Cache cache;
	public Consumer(Cache cache) {
		this.cache=cache;
	}
	@Override
	public void run() {
		while(true) {
			try {
				cache.consume();
				Thread.sleep(100);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}
}
class Producer implements Runnable{
	private Cache cache;
	public Producer(Cache cache) {
		this.cache=cache;
	}
	@Override
	public void run() {
		while(true) {
			try {
				cache.produce();
				Thread.sleep(100);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		
	}
	
}
public class ProducerConsumer {
	public static void main(String[] args) {
		Cache cache=new Cache(10);
		Producer pro=new Producer(cache);
		Consumer con=new Consumer(cache);
		int proThreadCount=4,conThreadCount=4;
		for(int i=0;i

使用管程实现生产者消费者问题

你可能感兴趣的:(OS)