-
2021-11-07 10:17:27
一、生产者消费者问题
生产者和消费者问题是计算机同步互斥的经典问题,其意思就是生产者把生产出来的产品放在仓库里,消费者把产品从仓库里取出来。仓库属于临界区,生产者和消费者一次只能一个进入临界区中。两个进程之间就有一个同步互斥问题,下面我将对该问题进行详细介绍。
二、思路分析
对于一个仓库,仓库的容量是有限的,对应的临界资源是有限的,假设仓库的容量是n。当仓库装满了,就不能允许生产者进行访问,如果仓库满了,生产者再把产品放进仓库就会导致仓库爆仓。与此同时,当库存为零时也不能允许消费者进入,这个不符合逻辑。基于这种思路,我们设置三个信号量empty、full和一个互斥锁。
三、代码实现
semaphore mutex=1; semaphore empty=n; semaphore full=0; //生产者 producer(){ while(1){ //生产者生产产品 P(empty);//判断仓库是否为空 P(mutex);//判断是否可以进入临界区 //放产品 V(full);//仓库里有多少产品 V(mutex);//释放互斥锁 } } //消费者 consumer(){ while(1){ P(full);//判断仓库是否有产品 P(mutex);//判断是否可以进入临界区 //放消费产品 V(empty);//仓库里增加一个空位 V(mutex);//释放互斥锁 } }
更多相关内容 -
经典消费者生产者问题
2017-12-21 16:09:442.我们应该判断的是如果消费者消耗光仓库的食物,我们应该让消费者们等待,然后notifyAll所有的生产者,直到生产者生产的食物等于仓库容量,我们可以停止生产,进入wait状态,然后唤醒所有消费者消费食物。...
首先你需要了解多线程的流程以及实现多线程的几种方法,同时你要理解什么是并行、并发,以及线程和进程的区别,这里做简要的区别。
线程:一个进程包括多个线程
并行:多个cpu实例或者多台机器同时执行一段处理逻辑,是真正的同时。
并发:通过cpu调度算法,让用户看上去同时执行,实际上从cpu操作层面不是真正的同时。并发往往在场景中有公用的资源,那么针对这个公用的资源往往产生瓶颈,我们会用TPS或者QPS来反应这个系统的处理能力。
之前看到过一篇博客,我觉得很形象的解释了并行和并发,下面我借用他的一个图片解释一下
就如同喝咖啡一样,并行是让一杯咖啡被两种人同时喝,而并发是有可能有两杯咖啡,两种人同时喝,看起来是同时进行,但不是真正的同时。
多线程的基本流程
新建状态(New):当线程对象对创建后,即进入了新建状态,如:Thread t = new MyThread();就绪状态(Runnable):当调用线程对象的start()方法(t.start();),线程即进入就绪状态。处于就绪状态的线程,只是说明此线程已经做好了准备,随时等待CPU调度执行,并不是说执行了t.start()此线程立即就会执行;
运行状态(Running):当CPU开始调度处于就绪状态的线程时,此时线程才得以真正执行,即进入到运行状态。注:就 绪状态是进入到运行状态的唯一入口,也就是说,线程要想进入运行状态执行,首先必须处于就绪状态中;
阻塞状态(Blocked):处于运行状态中的线程由于某种原因,暂时放弃对CPU的使用权,停止执行,此时进入阻塞状态,直到其进入到就绪状态,才 有机会再次被CPU调用以进入到运行状态。根据阻塞产生的原因不同,阻塞状态又可以分为三种:
1.等待阻塞:运行状态中的线程执行wait()方法,使本线程进入到等待阻塞状态;
2.同步阻塞 – 线程在获取synchronized同步锁失败(因为锁被其它线程所占用),它会进入同步阻塞状态;
3.其他阻塞 – 通过调用线程的sleep()或join()或发出了I/O请求时,线程会进入到阻塞状态。当sleep()状态超时、join()等待线程终止或者超时、或者I/O处理完毕时,线程重新转入就绪状态。
死亡状态(Dead):线程执行完了或者因异常退出了run()方法,该线程结束生命周期。
好了下面进入我们的生产者消费者问题
生产者消费者问题
考虑一个程序的怎么写首先应该有大概的流程,生产消费问题其实也就是生产——仓库——消费 模型
1.首先应该建立仓库类、消费者类、生产者类、以及最终的测试类。
2.我们应该判断的是如果消费者消耗光仓库的食物,我们应该让消费者们等待,然后notifyAll所有的生产者,直到生产者生产的食物等于仓库容量,我们可以停止生产,进入wait状态,然后唤醒所有消费者消费食物。大体的思路就是这样。
下面用真正的代码实现仓库类
package com.cn.hnust.controller; import sun.org.mozilla.javascript.internal.Synchronizer; import java.util.LinkedList; public class CangKu { private final int MAX_SIZE=100; //仓库最大容量 LinkedList<Object> linkedList= new LinkedList();//载体 public LinkedList<Object> getLinkedList() { return linkedList; } public void setLinkedList(LinkedList<Object> linkedList) { this.linkedList = linkedList; } /** * 生产者方法 * @param num */ public void produce(int num ){ synchronized (linkedList){ while(linkedList.size()+num>MAX_SIZE){ System.out.println("不能生产,食物够用"+num+"size==="+linkedList.size()); try { linkedList.wait(); }catch (Exception e){ e.printStackTrace(); } } for (int i=1;i<=num;++i){ linkedList.add(new Object()); } System.out.println("已经生产" +num+ "总共有"+linkedList.size()); linkedList.notifyAll(); } } public int getMAX_SIZE() { return MAX_SIZE; } /** * 消费者方法 * @param num */ public void consoume(int num ){ synchronized (linkedList){ while(linkedList.size()<num){ try { System.out.println("消费"+num +"size"+linkedList.size()); linkedList.wait(); }catch (Exception e){ e.printStackTrace(); } } for (int i=1;i<=num;++i){ linkedList.remove(); } System.out.println("【已经消费产品数】:" + num + "/t【现仓储量为】:" + linkedList.size()); linkedList.notifyAll(); } } }
生产类
package com.cn.hnust.controller; public class proudcter extends Thread { private int num; public int getNum() { return num; } public void setNum(int num) { this.num = num; } public CangKu getCangKu() { return cangKu; } public void setCangKu(CangKu cangKu) { this.cangKu = cangKu; } private CangKu cangKu; public proudcter(CangKu cangKu){ this.cangKu=cangKu; } public void proudce(int num) { cangKu.produce(num); } public void run(){ proudce(num); } }
消费者类
package com.cn.hnust.controller; public class consumers extends Thread { private int num; public int getNum() { return num; } public void setNum(int num) { this.num = num; } public CangKu getCangKu() { return cangKu; } public void setCangKu(CangKu cangKu) { this.cangKu = cangKu; } private CangKu cangKu; public consumers(CangKu cangKu1){ this.cangKu=cangKu1; } public void consum(int num) { cangKu.consoume(num); } public void run(){ consum(num); } }
主类
package com.cn.hnust.controller; public class PCTest { public static void main(String[] args) { CangKu cangKu =new CangKu(); proudcter proudcter =new proudcter(cangKu); proudcter proudcter1 =new proudcter(cangKu); proudcter proudcter2 =new proudcter(cangKu); proudcter proudcter3 =new proudcter(cangKu); proudcter proudcter4 =new proudcter(cangKu); proudcter proudcter5 =new proudcter(cangKu); consumers consumers =new consumers(cangKu); consumers consumers1 =new consumers(cangKu); consumers consumers2 =new consumers(cangKu); consumers consumers3 =new consumers(cangKu); proudcter.setNum(10); proudcter1.setNum(10); proudcter2.setNum(10); proudcter3.setNum(90); proudcter4.setNum(10); proudcter5.setNum(80); consumers.setNum(50); consumers1.setNum(20); consumers2.setNum(60); consumers3.setNum(10); consumers.start(); consumers1.start(); consumers2.start(); consumers3.start(); proudcter.start(); proudcter1.start(); proudcter2.start(); proudcter3.start(); proudcter4.start(); proudcter5.start(); } }
以上就是生产者消费者问题,如果有不对之处,希望指出。共同进步,谢谢。
-
多线程之消费者生产者问题
2018-08-01 22:19:55消费者生产者问题: 这个问题是一个多线程同步问题的经典案例,生产者负责生产对象,消费者负责将生成者产生的对象取出,两者不断重复此过程。这过程需要注意几个问题: 不论生产者和消费者有几个,必须保证: 1....消费者生产者问题:
这个问题是一个多线程同步问题的经典案例,生产者负责生产对象,消费者负责将生成者产生的对象取出,两者不断重复此过程。这过程需要注意几个问题:
不论生产者和消费者有几个,必须保证:
1.生产者每次产出的对象必须不一样,产生的对象有且仅有出现一次;
2.消费者每次取出的对象必须不一样,取出的对象有且仅有出现一次;
3.一定是先产生该对象,然后对象才能被取出,顺序不能乱;
第一种情况:
多个生产者轮流负责生产,多个消费者负责取出。一旦生产者产生一个对象,其他生产者不能生产,只能由消费者执行取出操作;
需要的对象有商品类、消费者、生产者;
//测试类 public class ProducerConsumer { public static void main(String[] args) { // 定义资源对象 Resource r = new Resource(); //定义一个生产者和一个消费者 Producer p = new Producer(r); Consumer c = new Consumer(r); //启动四个线程,2个负责生产者,两个消费者 Thread t1 = new Thread(p); Thread t2 = new Thread(p); Thread t3 = new Thread(c); Thread t4 = new Thread(c); t1.start(); t2.start(); t3.start(); t4.start(); } } //商品类 class Resource{ private String name; private int count = 1; private boolean flag = false; //产生商品 public synchronized void set(String name) { while (flag) { try { this.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } this.name = name + "---" + count++; System.out.println(Thread.currentThread().getName() + " 生产者" + this.name); flag = true; //唤醒所有线程 this.notifyAll(); } //取出商品 public synchronized void out() { while (!flag) { try { wait(); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println(Thread.currentThread().getName() + " 消费者________" + this.name); flag = false; this.notifyAll(); } } //定义生产者 class Producer implements Runnable{ private Resource res; public Producer(Resource res) { this.res = res; } @Override public void run() { while (true) { res.set("+商品+"); } } } //定义消费者 class Consumer implements Runnable{ private Resource res; Consumer(Resource res) { this.res = res; } @Override public void run() { while (true) { res.out(); } } }
运行结果是产生一个,随即取出一个,循环往复,其运行结果的部分如下:
Thread-2 消费者________+商品+---67821 Thread-1 生产者+商品+---67822 Thread-3 消费者________+商品+---67822 Thread-0 生产者+商品+---67823 Thread-2 消费者________+商品+---67823 Thread-1 生产者+商品+---67824 Thread-3 消费者________+商品+---67824 Thread-0 生产者+商品+---67825 Thread-2 消费者________+商品+---67825 Thread-1 生产者+商品+---67826 Thread-3 消费者________+商品+---67826 Thread-0 生产者+商品+---67827 Thread-2 消费者________+商品+---67827 Thread-1 生产者+商品+---67828 Thread-3 消费者________+商品+---67828 Thread-0 生产者+商品+---67829 Thread-2 消费者________+商品+---67829 Thread-1 生产者+商品+---67830 Thread-3 消费者________+商品+---67830 Thread-0 生产者+商品+---67831 Thread-2 消费者________+商品+---67831 Thread-1 生产者+商品+---67832
第二种情况:
目标:生产者与消费者轮换着抢夺执行权,但是生产者最多可以库存5个,消费者最多可以连续取出5个
此时需要定义一种中间对象:仓库类。该类是生产者和消费者共享的一块区域,里面数据类型选择链表结果存放产生的对象。仓库是有容量上限的,当数量达到上限后,生产者不允许继续生产产品.当前线程进入等待状态,等待其他线程唤醒。当仓库没有产品时,消费者不允许继续消费,当前线程进入等待状态,等待其他线程唤醒。
第一种解决方式,采用同步代码块(synchronized),结合着 wait() 和 notifyAll() 的方法,具体代码如下:
package Thread; /** * 2个消费者,3个生产者 */ import java.util.LinkedList; public class ProConThreadDemo { public static void main(String[] args) { Respository res = new Respository(); //定义2个消费者,3个生产者 Worker p1 = new Worker(res,"手机"); Worker p2 = new Worker(res,"电脑"); Worker p3 = new Worker(res,"鼠标"); Constomer c1 = new Constomer(res); Constomer c2 = new Constomer(res); Thread t1 = new Thread(p1,"甲"); Thread t2 = new Thread(p2,"乙"); Thread t3 = new Thread(p3,"丙"); Thread t4 = new Thread(c1,"aaa"); Thread t5 = new Thread(c2,"bbb"); t1.start(); t2.start(); t3.start(); t4.start(); t5.start(); } } //仓库类 class Respository{ private LinkedList<Product> store = new LinkedList<Product>(); //生产者的方法,用于向仓库存货 //最多只能有一个线程同时访问该方法. public synchronized void push(Product p,String ThreadName){ //设置仓库库存最多能存5个商品 /* 仓库容量最大值为5,当容量等于5的时候进入等待状态.等待其他线程唤醒 * 唤醒后继续循环,等到仓库的存量小于5时,跳出循环继续向下执行准备生产产品. */ while (store.size()==5){ try { System.out.println(ThreadName+" 发现:仓库已满,赶紧叫人运走"); //因为仓库容量已满,无法继续生产,进入等待状态,等待其他线程唤醒. this.wait(); }catch (InterruptedException e){ e.printStackTrace(); } } this.notifyAll(); store.addLast(p); System.out.println(ThreadName+" 给仓库添加 "+p.Name+p.Id+"号名称为 "+" 当前库存量为:"+store.size()); //为了方便观察运行结果,每次生产完后等待0.1秒 try { Thread.sleep(100); }catch (InterruptedException e){ e.printStackTrace(); } } //消费者的方法,用于仓库出货 //最多只能有一个线程同时访问该方法. public synchronized void pop(String ThreadName){ /* 当仓库没有存货时,消费者需要进行等待.等待其他线程来唤醒 * 唤醒后继续循环,等到仓库的存量大于0时,跳出循环继续向下执行准备消费产品. */ while (store.size()==0){ try { System.out.println(ThreadName+" 发现:仓库空了,赶紧安排生产"); //因为仓库容量已空,无法继续消费,进入等待状态,等待其他线程唤醒. this.wait(); }catch (InterruptedException e){ e.printStackTrace(); } } this.notifyAll(); //定义对象。存放pollFirst()方法删除的对象, Product p = store.pollFirst(); System.out.println(ThreadName+"买走 "+p.Name+p.Id+" 当前库存量为:"+store.size()); //为了方便观察运行结果,每次取出后等待0.1秒 try { Thread.sleep(100); }catch (InterruptedException e){ e.printStackTrace(); } } } //产品类 class Product{ //产品的唯一标识Id public int Id; //产品的名称 public String Name; public Product(String name, int id) { Name = name; Id = id; } } //生产者 class Worker implements Runnable{ //关键字volatile 是为了保持 Id 的可见性,一旦Id被修改,其他任何线程用到Id的地方,都会相应修改 //否则下方run方法容易出问题,生产商品的Id和名称 与到时候消费者取出商品的Id和名称不一致 public volatile Integer Id = 0; public volatile String name; //引用一个产品 private Product p; //引用一个仓库 Respository res; boolean flag = true; public Worker(Respository res,String name) { this.res = res; this.name = name; } @Override public void run() { while (flag){ p = new Product(name,Id); res.push(new Product(this.p.Name,Id++),Thread.currentThread().getName()); } } } class Constomer implements Runnable{ boolean flag = true; //引用一个仓库 Respository res; public Constomer(Respository res) { this.res = res; } @Override public void run() { while (flag) { res.pop(Thread.currentThread().getName()); } } }
运行结果如下,可见仓库最多库存为5个,接近于实际生产
aaa 发现:仓库空了,赶紧安排生产 乙 给仓库添加 电脑0号名称为 当前库存量为:1 丙 给仓库添加 鼠标0号名称为 当前库存量为:2 甲 给仓库添加 手机0号名称为 当前库存量为:3 bbb买走 电脑0 当前库存量为:2 bbb买走 鼠标0 当前库存量为:1 甲 给仓库添加 手机1号名称为 当前库存量为:2 丙 给仓库添加 鼠标1号名称为 当前库存量为:3 乙 给仓库添加 电脑1号名称为 当前库存量为:4 aaa买走 手机0 当前库存量为:3 aaa买走 手机1 当前库存量为:2 aaa买走 鼠标1 当前库存量为:1 aaa买走 电脑1 当前库存量为:0 aaa 发现:仓库空了,赶紧安排生产 乙 给仓库添加 电脑2号名称为 当前库存量为:1 丙 给仓库添加 鼠标2号名称为 当前库存量为:2 甲 给仓库添加 手机2号名称为 当前库存量为:3 bbb买走 电脑2 当前库存量为:2 bbb买走 鼠标2 当前库存量为:1 甲 给仓库添加 手机3号名称为 当前库存量为:2 丙 给仓库添加 鼠标3号名称为 当前库存量为:3 乙 给仓库添加 电脑3号名称为 当前库存量为:4 aaa买走 手机2 当前库存量为:3 乙 给仓库添加 电脑4号名称为 当前库存量为:4 乙 给仓库添加 电脑5号名称为 当前库存量为:5
第二种方法,利用 lock类 替代 synchronized的使用,这样可以优化代码,主要是在唤醒的时候可以根据条件去唤醒指定的某些线程。例如:当库存为空的时候,第一种方法是唤醒所有等待的线程,也包括取出的线程;而此时lock类 可以设置在库存为空的时候,只唤醒生产线程,取出的线程依旧处于等待状态,具体代码如下:
package Thread; import java.util.LinkedList; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; public class ProConThreadPool { public static void main(String[] args) { Respository res = new Respository(); Worker p1 = new Worker(res,"手机"); Worker p2 = new Worker(res,"电脑"); Worker p3 = new Worker(res,"鼠标"); Constomer c1 = new Constomer(res); Constomer c2 = new Constomer(res); Thread t1 = new Thread(p1,"甲"); Thread t2 = new Thread(p2,"乙"); Thread t3 = new Thread(p3,"丙"); Thread t4 = new Thread(c1,"aaa"); Thread t5 = new Thread(c2,"bbb"); t1.start(); t2.start(); t3.start(); t4.start(); t5.start(); } } //仓库类 class Respository{ private Lock lock = new ReentrantLock(); private LinkedList<Product> store = new LinkedList<Product>(); private Condition condition_pro = lock.newCondition(); private Condition condition_con = lock.newCondition(); public LinkedList<Product> getStore() { return store; } public void setStore(LinkedList<Product> store) { this.store = store; } //向仓库存货 public void push(Product p,String ThreadName) throws InterruptedException{ lock.lock(); try { //设置仓库库存最多能存5个商品 while (store.size()==5){ System.out.println(ThreadName+" 发现:仓库已满,赶紧叫人运走"); condition_pro.await(); } condition_con.signalAll(); store.addLast(p); System.out.println(ThreadName+" 给仓库添加 "+p.Name+p.Id+"号名称为 "+" 当前库存量为:"+store.size()); }finally { lock.unlock(); } try { Thread.sleep(100); }catch (InterruptedException e){ e.printStackTrace(); } } //仓库出货 public void pop(String ThreadName) throws InterruptedException { lock.lock(); try{ while (store.size()==0){ System.out.println(ThreadName+" 发现:仓库空了,赶紧安排生产"); condition_con.await(); } condition_pro.signalAll(); Product p = store.pollFirst(); System.out.println(ThreadName+"买走 "+p.Name+p.Id+" 当前库存量为:"+store.size()); } finally { lock.unlock(); } try { Thread.sleep(100); }catch (InterruptedException e){ e.printStackTrace(); } } } class Product{ public int Id; public String Name; public Product(String name, int id) { Name = name; Id = id; } } class Worker implements Runnable{ public volatile Integer Id = 0; public volatile String name; //引用一个产品 private Product p; //引用一个仓库 Respository res; boolean flag = true; public Worker(Respository res,String name) { this.res = res; this.name = name; } @Override public void run(){ while (flag){ p = new Product(name,Id); try { res.push(new Product(this.p.Name,Id++),Thread.currentThread().getName()); }catch (InterruptedException e){ e.printStackTrace(); } } } } class Constomer implements Runnable{ boolean flag = true; //引用一个仓库 Respository res; public Constomer(Respository res) { this.res = res; } @Override public void run() { while (flag) { try { res.pop(Thread.currentThread().getName()); } catch (InterruptedException e) { e.printStackTrace(); } } } }
运行结果与上面类似:
aaa 发现:仓库空了,赶紧安排生产 bbb 发现:仓库空了,赶紧安排生产 丙 给仓库添加 鼠标0号名称为 当前库存量为:1 乙 给仓库添加 电脑0号名称为 当前库存量为:2 甲 给仓库添加 手机0号名称为 当前库存量为:3 aaa买走 鼠标0 当前库存量为:2 bbb买走 电脑0 当前库存量为:1 bbb买走 手机0 当前库存量为:0 乙 给仓库添加 电脑1号名称为 当前库存量为:1 甲 给仓库添加 手机1号名称为 当前库存量为:2 aaa买走 电脑1 当前库存量为:1 丙 给仓库添加 鼠标1号名称为 当前库存量为:2 aaa买走 手机1 当前库存量为:1 甲 给仓库添加 手机2号名称为 当前库存量为:2 乙 给仓库添加 电脑2号名称为 当前库存量为:3 bbb买走 鼠标1 当前库存量为:2 丙 给仓库添加 鼠标2号名称为 当前库存量为:3 aaa买走 手机2 当前库存量为:2 甲 给仓库添加 手机3号名称为 当前库存量为:3 bbb买走 电脑2 当前库存量为:2 乙 给仓库添加 电脑3号名称为 当前库存量为:3 丙 给仓库添加 鼠标3号名称为 当前库存量为:4
-
生产者-消费者问题(C++信号量实现)
2019-10-27 16:05:10生产者-消费者问题是很经典的线程同步问题,这段代码给出的是多生产者、多消费者、有界缓冲区的一个C++实现。 常见的生产者消费者实现一般是Unix或Linux下的使用Pthread完成的,这里使用WINDOWS环境下的API实现。 #...生产者-消费者问题是很经典的线程同步问题,这段代码给出的是多生产者、多消费者、有界缓冲区的一个C++实现。
常见的生产者消费者实现一般是Unix或Linux下的使用Pthread完成的,这里使用WINDOWS环境下的API实现。#include<iostream> #include<queue> #include<Windows.h> #include<unordered_map> using namespace std; static const int QUEUE_SIZE = 10; static HANDLE semEmpty = NULL; static HANDLE semFull = NULL; static const int PRODUCER_SIZE = 3; static const int CONSUMER_SIZE = 10; static HANDLE event = NULL; static CRITICAL_SECTION queueMutex;//临界区锁,用于维护临界区,保护bufferQueue static queue<int> bufferQueue; static int goodsNum = 0;//当前生产商品的序号 unordered_map<DWORD,int> id;//hashmap用来记录线程id与进程序号的映射 DWORD WINAPI ProducerThread() { while (true) { if (WAIT_TIMEOUT != WaitForSingleObject(event, 0)) break; WaitForSingleObject(semEmpty, INFINITE); EnterCriticalSection(&queueMutex); bufferQueue.push(goodsNum++); cout << "生产者"<< id[GetCurrentThreadId()] <<"正在生产" << bufferQueue.back()<<"号商品"<< endl; LeaveCriticalSection(&queueMutex); ReleaseSemaphore(semFull, 1, NULL); } return 0; } DWORD WINAPI ConsumerThread() { while (true) { if (WAIT_TIMEOUT != WaitForSingleObject(event, 0)) break; WaitForSingleObject(semFull, INFINITE); EnterCriticalSection(&queueMutex); cout << "\t\t\t消费者" << id[GetCurrentThreadId()] << "正在消费" << bufferQueue.front() << "号商品" << endl; bufferQueue.pop(); LeaveCriticalSection(&queueMutex); ReleaseSemaphore(semEmpty, 1, NULL); } return 0; } int main(void) { HANDLE ThreadArray[CONSUMER_SIZE+PRODUCER_SIZE]; InitializeCriticalSection(&queueMutex); // queue读写同步 event = CreateEvent(NULL,true,false,NULL); // 手动控制、初始为非激发状态 semEmpty = CreateSemaphore(NULL, QUEUE_SIZE, QUEUE_SIZE, NULL); semFull = CreateSemaphore(NULL, 0, QUEUE_SIZE, NULL); for (int i = 0; i < PRODUCER_SIZE; i++) { DWORD tid; ThreadArray[i] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ProducerThread, NULL, 0, &tid); pair<DWORD, int> pa; pa.first = tid; pa.second = i+1; id.insert(pa); } for (int i = 0; i < CONSUMER_SIZE; i++) { DWORD tid; ThreadArray[PRODUCER_SIZE+i] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ConsumerThread, NULL, 0, &tid); pair<DWORD, int> pa; pa.first = tid; pa.second = i+1; id.insert(pa); } Sleep(10000); SetEvent(event);//10秒后退出生产者、消费者线程 WaitForMultipleObjects(PRODUCER_SIZE+CONSUMER_SIZE, ThreadArray, TRUE, INFINITE); for (int i = 0; i < PRODUCER_SIZE+CONSUMER_SIZE; i++) CloseHandle(ThreadArray[i]); CloseHandle(semEmpty); CloseHandle(semFull); CloseHandle(event); DeleteCriticalSection(&queueMutex); system("pause"); return 0; }
-
生产者消费者问题 C++实现
2018-06-29 17:00:03生产者消费者问题 C++实现 知识准备 thread 介绍 成员类 成员函数 sleep_for 介绍 mutex 介绍 成员函数 unique_lock 介绍 成员函数 codition_variable 介绍 成员函数 代码示例 生产者消费者问题 ... -
操作系统实验二总结(生产者消费者问题)
2019-05-13 22:21:07为了这个实验二,资料查了巨多,pv操作什么的好不容易弄明白...3.消费者要是能放到buffer里就看生产者等待队列里有没有人,有人就唤醒一个生产者。 4.要是buffer只有1那么大,最终完成链表中必定是生产者和消费者交... -
生产者消费者问题的C语言实现
2018-06-09 12:52:18实验六 生产者/消费者问题实验一、实验目的掌握Linux下生产者/消费者问题算法的实现 二、实验原理1.clone系统调用:功能:创建一个轻进程或线程用法:intclone (int (*fn)(void *arg),void *stack,int flag,void *... -
经典生产者-消费者问题解析
2020-04-09 14:35:331.生产者-消费者问题 生产者和消费者问题在现实系统中是很普遍的。例如在一个多媒体系统中,生产者编码视频帧,而消费者消费(解码)视频帧,缓冲区的目的就是减少视频流的抖动。又如在图形用户接口设计中,生产者... -
【操作系统】生产者消费者问题
2018-08-11 00:43:20生产者消费者模型 生产者消费者模型 一、 生产者消费者问题 二、 问题分析 三、 伪代码实现 四、代码实现(C++) 五、 互斥锁与条件变量的使用比较 一、 生产者消费者问题 生产者消费者问题... -
操作系统_生产者消费者问题
2020-03-17 21:29:531,生产者消费者问题 问题的提出 初步思考 进程资源共享关系和同步关系分析 问题的具体解决 第一搏 存在的问题 第二搏 多维度思考 1,单生产者、单消费者、多缓冲区 2,多生产者、多消费者、单缓冲 3,单... -
多线程解决生产者与消费者问题
2016-09-03 23:07:06生产者消费者问题是一个很有名的线程同步问题,以前学操作系统时,没怎么搞懂,直到现在学java学到多线程这一块才搞懂。该问题描述的是两个共享固定大小的缓冲区的线程问题。生产者的主要作用是生成一定量的数据放到... -
生产者消费者问题
2022-01-27 21:44:12生产者/消费者问题,也被称作有限缓冲问题。 可以描述为:两个或者更多的线程共享同一个缓冲区,其中一个或多个线程作为“生产者”会不 断地向缓冲区中添加数据,另一个或者多个线程作为“消费者”从缓冲区中取走... -
计算机操作系统——进程同步实验之生产者和消费者问题
2022-01-17 14:13:16一、实验内容 ...三个生产者向两个消费者提供消息,它们共享一个有界缓冲池,缓冲池有四个缓冲区,生产者向其中投放消息,消费者从中取得消息。假定这些生产者和消费者互相等效,只要缓冲池未满,生产 -
Java可视化实现生产者消费者问题
2019-09-28 22:14:06引言:生产者消费者问题是一个十分经典的多线程问题。为了更加形象地描述这个问题,采用可视化的形式展示此过程。 -
进程同步问题——生产者—消费者问题
2020-03-11 21:58:50进程同步问题——生产者—消费者问题 问题梗概 生产者—消费者问题是相互合作关系的进程关系的一种抽象,是一个广义的概念,可以代表一类具有相同属性的进程 生产者:一个或者是多个生产者将生产的数据存入缓冲区中... -
Java多种方式解决生产者消费者问题(十分详细)
2018-08-16 08:40:50生产者消费者问题 一、问题描述 生产者消费者问题(Producer-consumer problem),也称有限缓冲问题(Bounded-buffer problem),是一个多线程同步问题的经典案例。生产者生成一定量的数据放到缓冲区中,... -
【操作系统】实验 生产者-消费者问题解决方案
2020-01-26 11:52:13Java实现生产者-消费者问题解决方案实验 -
生产者消费者问题-代码详解(Java多线程)
2020-06-13 11:10:07文章目录一、生产者消费者问题二、代码实现三、拓展知识 一、生产者消费者问题 生产者消费者问题(英语:Producer-consumer problem),也称有限缓冲问题(英语:Bounded-buffer problem),是一个多线程同步问题的... -
操作系统实验 生产者消费者问题详解
2021-01-09 16:18:44操作系统课程设计 生产者消费者实验报告 一、实验目的 加深对进程概念的理解,明确进程与程序的区别。 认识并发执行的本质。 理解和掌握Linux和Windows进程通信系统调用的功能,通过实验和学习,提高对进程痛惜系统... -
操作系统学习笔记-信号量及PV操作与进程互斥和消费者生产者问题
2017-08-10 03:34:41看到了关于多进程的互斥问题 大体就是说考虑到多进程的程序可能会共用共同的某一部分内容,这部分称为临界区 但是由于cpu的调度,如果有两个进程A,B A在使用临界区的时候,由于种种原因被下CPU换成了B上CPU执行 但是... -
C++实现生产者和消费者模型
2020-09-17 08:50:04C++实现生产者和消费者模型 C++实现生产者和消费者模型1、实现细节1、单生产者-单消费者模型参考 C++实现生产者和消费者模型 1、实现细节 具体的实现逻辑是构建一个queue来存储生产的数据,queue不满时可以生产,不... -
进程调度算法-生产者消费者问题
2019-06-14 23:13:33@进程调度算法之生产者消费者问题 生产者消费者问题 问题介绍 生产者生产产品,消费者消费产品,两者的资源存储在同一个资源池。 因此,问题来了,生产者生产商品需要在资源池的存储范围内;然而消费者消费的资源... -
操作系统生产者-消费者问题(PV操作)(Java实现)
2020-12-31 09:29:30生产者和消费者对缓冲区互斥访问是互斥关系,同时生产者和消费者又是一个相互协作的关系,只有生产者生产之后,消费者只能才能消费,它们还是同步关系。 (2)、整理思路。只有生产生产者和消费者进程,正好是这两个... -
进程同步经典问题(一)【生产者和消费者问题】
2018-10-11 20:43:14一组生产者进程和一组消费者进程共享一个初始为空、大小为n的缓冲区,只有缓冲区没满时,生产者才能把消息放入缓冲区,否则必须等待;只有缓冲区不空时,消费者才能从中取出消息,否则只有等待。由于缓冲区是临界... -
生产者-消费者问题
2018-03-28 19:04:43问题基本描述生产者消费者问题是一个著名的进程同步的问题。它描述的是:有一群生产者进程在生产产品,并将这些产品提供给消费者进程去消费。为使生产者进程与消费者进程能并发执行,在两者之间设置了一个具有n个... -
操作系统 - C语言实现生产者消费者问题
2018-05-30 10:34:29同步互斥问题 - 生产者消费者问题 问题描述: 有多个进程:多个生产者进程和多个消费者进程共享一个初始为空、固定大小为n的缓存(缓冲区)。生产者的工作是制造数据,只有缓冲区没满时,生产者才能把消息放入... -
生产者消费者问题c语言_C中的生产者消费者问题
2020-09-13 11:50:37生产者消费者问题c语言Here you will learn about producer consumer problem in C. 在这里,您将了解C语言中的生产者消费者问题。 Producer consumer problem is also known as bounded buffer problem. In this ... -
操作系统 生产者消费者问题
2016-04-16 13:35:45那个缓冲区的作用,求演示一下,还有,编程序的时候,我设定了信号量,PV原语,但是 不知道主函数输入什么,是输入生产或者消费等一系列动作么?它的互斥体现在哪 -
PV操作解决进程同步问题,生产者消费者问题为例
2019-07-08 19:49:23所以在这种情况中,生产者与消费者存在同步关系,而且各个生产者之间、各个消费者之间存在互斥关系,他们必须互斥地访问缓冲区。 解题如下: 定义四个信号量: empty——表示缓冲区是否为空,初值为n。 full... -
[操作系统]生产者/消费者问题
2018-04-13 21:32:47生产者/消费者问题也叫缓存绑定问题(bounded- buffer),是一个经典的、多进程同步问题。 单生产者和单消费者 仓库容量为一的情况 问题分析: 仓库有空位时,生产者才能生产产品,并放入仓库中; 仓库中...