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

模拟AND信号量解决生产者-消费者问题

问题描述:
AND型信号量和记录型信号量原理大致相同。
想较与记录型信号量,AND型信号量主要做了以下改动:
 用Swait(empty,mutex)来代替wait(empty)和wait(mutex);
• 用Ssignal(mutex,full)来代替signal(mutex)和signal(full);
• 用Swait(full,mutex)代替wait(full)和wait(mutex);
• 用Ssignal(mutex,empty)代替Signal(mutex)和
Signal(empty)。

记录型信号量解决生产者消费者问题请点如下链接:
https://blog.csdn.net/qq_45273552/article/details/109054767

参考代码(原语):
Var mutex,empty,full:semaphore:=1,n,0;
    buffer:array[0,...,n-1]of item;
    in,out:integer:=0,0;
    begin
        parbegin
            proceducer:begin
                    repeat
                    .
                    .
                    .
                    producer an item nextp;
                    .
                    .
                    .
                    wait(empty);
                    wait(mutex);
                    buffer(in):=nextp;
                    in:=(in+1)mod n;
                    signal(mutex);
                    signal(full);
                    until false;
    	           end
            consumer:begin
                    repeat
                    wait(full);
  	                wait(mutex);
                   nextc:=buffer(out);
                   out:=(out+1)mod n;
                   signal(mutex);
                    signal(empty);
   	               consumer the item in neXtg;
                    until false;
                end
        parend
    end

java代码实现:

import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class Main {
    
    
	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;
	/*
	Lock锁,可以得到和 synchronized一样的效果,即实现原子性、有序性和可见性。
	相较于synchronized,Lock锁可手动获取锁和释放锁、可中断的获取锁、超时获取锁。
	它是一个接口,两个直接实现类:
	ReentrantLock(重入锁),
 	ReentrantReadWriteLock(读写锁)。
	
	此处用的可重入锁 ReentrantLock
	与synchronized相比,重入锁有着显式的操作过程,开发人员必须手动的指定何时加锁(调用lock方法),何时释放锁(调用unlock方法)。因此,重入锁对逻辑的控制性要好于synchronized
	*/
	/*	
		Condition接口介绍:
		 任意一个Java对象,都拥有一组监视器方法(定义在Object类中),主要包括wait,notify,notifyAll方法,这些方法与synchornized关键字相配合,可以实现等待/通知模式。
    Condition接口也提供了类似的Object的监视器方法,与Lock配合可以实现等待/通知模式。(具体用法请自行搜索)
    
	*/
	//可重入锁和条件变量
	static Lock lock = new ReentrantLock();
	static Condition condition = lock.newCondition();
	
	
	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();
	}

	//定义wait信号方法:加锁
	public void SWAIT(Semaphore...list) {
    
    
		lock.lock();

		  //如果资源不足,就挂起线程,并将线程插入到condition的队列中
		  while (true) {
    
    
		    int count=0;
		    for (Semaphore semaphore:list){
    
    
		      if(semaphore.availablePermits()>0){
    
    
		        count++;
		      }
		    }
		    if(count == list.length){
    
    
		      break;
		    }
		    try {
    
    
				condition.await();
			} catch (InterruptedException e) {
    
    
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		  }
		  for (Semaphore semaphore:list){
    
    
		    try {
    
    
				semaphore.acquire();
			} catch (InterruptedException e) {
    
    
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		  }

		  lock.unlock();
	}
	//定义signal信号方法:释放锁
	public void SSIGNAL(Semaphore...list) {
    
    
		  try {
    
    
			lock.tryLock(1, TimeUnit.SECONDS);
		} catch (InterruptedException e) {
    
    
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		  for (Semaphore semaphore:list){
    
    
		    semaphore.release();
		  }
		  //唤醒等待队列中的一个线程
		  condition.signal();
		  lock.unlock();
	}
	
	/**
	 * 共享缓冲区
	 * */
	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) {
    
    
				SWAIT(empty,mutex);
				buffers[in].in();
				in=(in+1)%bufferSize;
				SSIGNAL(mutex,full);
			}
		}
	}
	/**
	 * 消费者
	 */
	class Customer extends Thread{
    
    
		Buffer[] buffers;
		public Customer(Buffer[] buffers) {
    
    
			this.buffers=buffers;
		}
		
		@Override
		public void run() {
    
    
			while(true) {
    
    
				SWAIT(full,mutex);
				buffers[out].out();
				out=(out+1)%bufferSize;
				SSIGNAL(mutex,empty);
			}
		}
	}
	
}

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

猜你喜欢

转载自blog.csdn.net/qq_45273552/article/details/109055936