ICode9

精准搜索请尝试: 精确搜索
首页 > 系统相关> 文章详细

【进程同步】经典问题(生产多种类产品的生产者--消费多种类产品的消费者问题)

2020-12-11 12:32:43  阅读:183  来源: 互联网

标签:warehourse name 进程同步 -- 仓库 生产者 mutex 产品 种类


多生产者–多消费者问题(数量为一的资源共享区)

1.问题描述

现在有一个产品共享仓库,每次其中只能生产并放一件产品(A产品或B产品)。生产者A生产A产品放入,生产者B生产B产品放入,消费者A消费产品A,消费者B消费产品B。且只有共享仓库没有产品时,生产者才能生产产品放入,而只有共享仓库中有属于消费者目标产品时,消费者才能消费。

如下图所示
在这里插入图片描述

2.确立同步关系

  • 当仓库为空时,生产者A(生产者B)可以放入产品A(产品B)
    说明: 由于生产者放入产品的事件是在仓库为空的事件之后,且仓库库存只有一,所以这里应该设置一个同步信号量为inventory= 1
  • 生产者A产品A产品,消费者A消费A产品
    说明: 生产者A明显和消费者A之间存在同步关系,且每次只生产(消费)一件产品,因此这里设置goodsA=0作为产品A 的同步信号量
  • 生产者B生产B产品,消费者B消费B产品
    说明: 生产者B明显和消费者B之间存在同步关系,且每次只生产(消费)一件产品,因此这里设置goodsB=0作为产品B的同步信号量

3.确立互斥关系

生产者和消费者互斥访问共享仓库,所以这里设置mutex作为共享仓库的互斥信号量

4.伪代码演示

Semaphore mutex = 1;       // 资源共享区互斥信号量
Semaphore goodsA = 0;      // 产品A同步信号量
Semaphore goodsB = 0;      // 产品B同步信号量
Semaphore inventory= 1;  // 仓库库存同步信号量
/*生产者A*/
ProductorA{
	while(true){
		P(inventory); //此时占用一个仓库库存
		
		P(mutex);
		生产产品A,并放入;
		V(mutex);
		
		V(goodsA);//生产一个产品A,goodsA+1
	}
}
/*生产者B*/
ProductorB{
	while(true){
		P(inventory); //此时占用一个仓库库存
		
		P(mutex);
		生产产品B,并放入;
		V(mutex);
		
		V(goodsB);//生产一个产品B,goodsB+1
	}
}
ConsumerA{
	while(true){
		P(goodsA);//占用其中产品A goodsA-1
		
		P(mutex);
		消费产品A;
		V(mutex);
		
		V(inventory);//释放一个仓库库存 inventory+1
	}
}
ConsumerB{
	while(true){
		P(goodsB);//占用其中产品B goodsB-1
		
		P(mutex);
		消费产品B;
		V(mutex);
		
		V(inventory);//释放一个仓库库存 inventory+1
	}
	
}

举例说明:生产者A与生产者B时并发执行,当生产者A进程执行时,由于占用了inventory仓库库存同步信号量,所以当调用到生产者B进程时会被阻塞。因此,只有当消费者A进程执行完成消费产品A之后,释放inventory的同时当系统调度到生产者B进程时,生产者B进程才被执行,生产者A进程也由于inventory被生产者B进程占用而阻塞。

5.Java多线程演示

public class MoreProductorConsumer {
    private static Semaphore mutex = new Semaphore(1);
    private static Semaphore goodsA = new Semaphore(0);
    private static Semaphore goodsB = new Semaphore(0);
    private static Semaphore inventory = new Semaphore(1);
    static class Warehourse{
        void  PutGoods(String type){
            System.out.println("目前仓库拥有一件 "+type+" 等待消费者消费");
        }
        void SaleGoods(String type){
            System.out.println("目前仓库消费一件 "+type+",生产者可以恢复生产");
        }
    }
    static class ProductorA implements Runnable{
        String name;
        Warehourse warehourse;
        ProductorA(String name,Warehourse warehourse){
            this.name=name;
            this.warehourse = warehourse;
        }
        @Override
        public void run() {
            while(true){
                try {
                    inventory.acquire();//P(inventory)
                    mutex.acquire();//P(mutex)
                    /*生产者A开始生产*/
                    Thread.sleep(1000);
                    System.out.println("--------------------");
                    System.out.println("生产者A:生产"+name+"放入仓库中");
                    warehourse.PutGoods(name);
                    /*生产者A生产结束*/
                    mutex.release();//V(mutex)
                    goodsA.release();//V(goodsA)
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    static class ProductorB implements Runnable{
        String name;
        Warehourse warehourse;
        ProductorB(String name,Warehourse warehourse){
            this.name=name;
            this.warehourse = warehourse;
        }
        @Override
        public void run() {
           while(true){
               try {
                   inventory.acquire();//P(inentory)
                   mutex.acquire();//P(mutex)
                    /*生产者B开始生产*/
                   Thread.sleep(1000);
                   System.out.println("--------------------");
                   System.out.println("生产者B:生产"+name+"放入仓库中");
                   warehourse.PutGoods(name);
                    /*生产者B生产结束*/
                   mutex.release();//V(mutex)
                   goodsB.release();//V(goodsB)
               } catch (InterruptedException e) {
                   e.printStackTrace();
               }

           }
        }
    }
    static class ConsumerA implements Runnable{
        String name;
        Warehourse warehourse;
        ConsumerA(String name,Warehourse warehourse){
            this.name=name;
            this.warehourse = warehourse;
        }
        @Override
        public void run() {
            while(true){
                try{
                    goodsA.acquire();//P(goodsA)
                    mutex.acquire();//P(mutex)
                     /*消费者A开始生产*/
                    Thread.sleep(1000);
                    System.out.println("--------------------");
                    System.out.println("消费者A:消费"+name);
                    warehourse.SaleGoods(name);
                    /*消费者A生产结束*/
                    mutex.release();//V(mutex)
                    inventory.release();//V(inventory)
                }catch (Exception e){
                    e.printStackTrace();
                }
            }
        }
    }
    static class ConsumerB implements Runnable{
        String name;
        Warehourse warehourse;
        ConsumerB(String name,Warehourse warehourse){
            this.name=name;
            this.warehourse = warehourse;
        }
        @Override
        public void run() {
           while (true){
               try{
                   goodsB.acquire();//P(goodsB)
                   mutex.acquire();//P(mutex)
                   Thread.sleep(1000);
                   System.out.println("--------------------");
                   System.out.println("消费者B:消费"+name);
                   warehourse.SaleGoods(name);
                   mutex.release();//V(mutex)
                   inventory.release();//V(inventory)
               }catch (Exception e){
                   e.printStackTrace();
               }
           }
        }
    }

    public static void main(String[] args) {
        Warehourse warehourse = new Warehourse();
       	ExecutorService service = Executors.newFixedThreadPool(4);
        try{
            service.submit(new ProductorA("产品A",warehourse));
            service.submit(new ProductorB("产品B",warehourse));
            service.submit(new ConsumerA("产品A",warehourse));
            service.submit(new ConsumerB("产品B",warehourse));
        }catch (Exception e){
            e.printStackTrace();
            service.shutdown();
        }
    }
}

6.结果分析

----------------------------------------------------
生产者A:生产产品A放入仓库中
目前仓库拥有一件 产品A 等待消费者消费
----------------------------------------------------
消费者A:消费产品A
目前仓库消费一件 产品A,生产者可以恢复生产
----------------------------------------------------
生产者B:生产产品B放入仓库中
目前仓库拥有一件 产品B 等待消费者消费
----------------------------------------------------
消费者B:消费产品B
目前仓库消费一件 产品B,生产者可以恢复生产
----------------------------------------------------
生产者A:生产产品A放入仓库中
目前仓库拥有一件 产品A 等待消费者消费
----------------------------------------------------

通过结果可以分析得到,仓库中只能存放一件产品,只有当仓库中的产品被消费后,才能执行下一步生产者进程生产产品。

多生产者–多消费者问题(多数量的资源共享区)

1. 问题描述:

一组生产者向一组消费者生产多种类的产品,他们之间共享同一个资源区,消费者消费生产者指定生产的产品,同时共享区内只能存有一种产品。

  • 与单一数量的资源共享区不同的是,此时的共享区可以存在同类多量的产品。
  • 与生产单一种类产品的生产者–消费单一种类产品的消费者问题不同的是,这里加多了一个产品种类,同时也增加了一个仓库种类只能存在一种产品的限制

如下图所示:
在这里插入图片描述

2.确立同步关系

  • 同步事件1->共享仓库产品A未满时,生产者A生产产品A,消费者A可以消费
    说明:这里可以设立Aempty=M,相当于确定仓库中所能存放产品的最大容量
  • 同步事件2->共享仓库产品B未满时,生产者B生产产品B,消费者B可以消费
    说明:这里可以设立Bempty=M,相当于确定仓库中所能存放产品的最大容量
  • 同步事件3->共享仓库A非空时,消费者A 消费 生产者A 生产的A产品
    说明:这里可以设立Afull=0,相当于在仓库A非空时,需要消费者A的数量
  • 同步事件4->共享仓库B非空时,消费者B 消费 生产者B 生产的B产品
    说明:这这里可以设立Bfull=0,相当于在仓库B非空时,需要消费者B的数量
  • 同步事件-5>只有共享仓库没有产品时才可生产产品A/B
    说明:这这里可以设立Productable=1,相当于生产者A或生产者B进行生产的“通行证”。只有拥有此这个“通行证”才可生产产品,从而做到将生产者A与生产者B的生产分离。

3.确立互斥关系

生产者和消费者不可能同时访问仓库共享区。

4.伪代码演示

Semaphore Aempty=M;
Semaphore Bempty=N;
Semaphore Afull=0;
Semaphore Bfull=0;
Semaphore Productable=1;  //生产通行证
Semaphore Amutex=1;       //控制生产者A Productable检测以及Acount的增值
Semaphore AmutexC=1;      //控制消费者A Productable检测以及Acount的减值
Semaphore Bmutex=1;       //控制生产者B Productable检测以及Bcount的增值
Semaphore BmutexC=1;      //控制消费者B Productable检测以及Bcount的减值
int Acount=0;             //用于计算生产者A生产产品A的数量
int Bcount=0;             //用于计算生产者B生产产品B的数量
/*生产者A*/
ProductorA{
	P(Amutex);
	if(Acount == 0) P(Productable);
	Acount++;
	V(Amutex);
	P(Aempty);
	生产产品A;
	V(Afull);
}
/*生产者B*/
ProductorB{
	P(Bmutex);
	if(Bcount == 0) P(Productable);
	Bcount++;
	V(Bmutex);
	P(Bempty);
	生产产品B;
	V(Bfull);
}
/*消费者A*/
ConsumerA{
	P(Afull);
	消耗产品A;
	P(AmutexC);
	Acount--;
	if(Acount == 0) V(Productable);
	V(AmutexC);
	V(Aempty);
}
/*消费者B*/
ConsumerB{
	P(Bfull);
	消耗产品B;
	P(BmutexC);
	Bcount--;
	if(Bcount == 0) V(Productable);
	V(BmutexC);
	V(Bempty);
}

标签:warehourse,name,进程同步,--,仓库,生产者,mutex,产品,种类
来源: https://blog.csdn.net/qq_41266147/article/details/110949220

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有