Java implementation: "Operating System Experiment One": Simulate recording semaphore to solve the producer-consumer problem

Analog recording semaphore solves producer-consumer problem

The producer consumer problem is one of the classic examples of java multithreading.

  • Solve the producer-consumer problem with recorded semaphores
  • Assuming that there are n buffers in the common buffer pool between the producer and the consumer, the
    mutex semaphore mutex can be used to realize the mutual exclusive use of the buffer pool by the processes;
    • The semaphore empty and full are used to indicate buffer
    The number of empty buffers and full buffers in the pool .
    • Assuming that these producers and consumers are equivalent to each other, as long as the buffer pool is not full, the
    producer can send a message to the buffer pool;
    • As long as the buffer pool is not empty, the consumer can take a message from the buffer pool .

Reference Code:

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 implementation and analysis;

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);
			}
		}
	}
	
}

operation result:
Insert picture description here

Guess you like

Origin blog.csdn.net/qq_45273552/article/details/109054767