精华内容
下载资源
问答
  • 操作系统经典问题之生产者消费者问题
    千次阅读
    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:44
    2.我们应该判断的是如果消费者消耗光仓库的食物,我们应该让消费者们等待,然后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++实现。 常见的生产者消费者实现一般是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:33
    1.生产者-消费者问题 生产者和消费者问题在现实系统中是很普遍的。例如在一个多媒体系统中,生产者编码视频帧,而消费者消费(解码)视频帧,缓冲区的目的就是减少视频流的抖动。又如在图形用户接口设计中,生产者...
  • 【操作系统】生产者消费者问题

    万次阅读 多人点赞 2018-08-11 00:43:20
    生产者消费者模型 生产者消费者模型 一、 生产者消费者问题 二、 问题分析 三、 伪代码实现 四、代码实现(C++) 五、 互斥锁与条件变量的使用比较 一、 生产者消费者问题 生产者消费者问题...
  • 操作系统_生产者消费者问题

    千次阅读 多人点赞 2020-03-17 21:29:53
    1,生产者消费者问题 问题的提出 初步思考 进程资源共享关系和同步关系分析 问题的具体解决 第一搏 存在的问题 第二搏 多维度思考 1,单生产者、单消费者、多缓冲区 2,多生产者、多消费者、单缓冲 3,单...
  • 多线程解决生产者消费者问题

    千次阅读 2016-09-03 23:07:06
    生产者消费者问题是一个很有名的线程同步问题,以前学操作系统时,没怎么搞懂,直到现在学java学到多线程这一块才搞懂。该问题描述的是两个共享固定大小的缓冲区的线程问题。生产者的主要作用是生成一定量的数据放到...
  • 生产者消费者问题

    千次阅读 2022-01-27 21:44:12
    生产者/消费者问题,也被称作有限缓冲问题。 可以描述为:两个或者更多的线程共享同一个缓冲区,其中一个或多个线程作为“生产者”会不 断地向缓冲区中添加数据,另一个或者多个线程作为“消费者”从缓冲区中取走...
  • 一、实验内容 ...三个生产者向两个消费者提供消息,它们共享一个有界缓冲池,缓冲池有四个缓冲区,生产者向其中投放消息,消费者从中取得消息。假定这些生产者消费者互相等效,只要缓冲池未满,生产
  • Java可视化实现生产者消费者问题

    千次阅读 2019-09-28 22:14:06
    引言:生产者消费者问题是一个十分经典的多线程问题。为了更加形象地描述这个问题,采用可视化的形式展示此过程。
  • 进程同步问题——生产者消费者问题 问题梗概 生产者消费者问题是相互合作关系的进程关系的一种抽象,是一个广义的概念,可以代表一类具有相同属性的进程 生产者:一个或者是多个生产者将生产的数据存入缓冲区中...
  • Java多种方式解决生产者消费者问题(十分详细)

    万次阅读 多人点赞 2018-08-16 08:40:50
    生产者消费者问题 一、问题描述 生产者消费者问题(Producer-consumer problem),也称有限缓冲问题(Bounded-buffer problem),是一个多线程同步问题的经典案例。生产者生成一定量的数据放到缓冲区中,...
  • Java实现生产者-消费者问题解决方案实验
  • 生产者消费者问题-代码详解(Java多线程)

    千次阅读 多人点赞 2020-06-13 11:10:07
    文章目录一、生产者消费者问题二、代码实现三、拓展知识 一、生产者消费者问题 生产者消费者问题(英语:Producer-consumer problem),也称有限缓冲问题(英语:Bounded-buffer problem),是一个多线程同步问题的...
  • 操作系统课程设计 生产者消费者实验报告 一、实验目的 加深对进程概念的理解,明确进程与程序的区别。 认识并发执行的本质。 理解和掌握Linux和Windows进程通信系统调用的功能,通过实验和学习,提高对进程痛惜系统...
  • 看到了关于多进程的互斥问题 大体就是说考虑到多进程的程序可能会共用共同的某一部分内容,这部分称为临界区 但是由于cpu的调度,如果有两个进程A,B A在使用临界区的时候,由于种种原因被下CPU换成了B上CPU执行 但是...
  • C++实现生产者消费者模型

    千次阅读 2020-09-17 08:50:04
    C++实现生产者消费者模型 C++实现生产者消费者模型1、实现细节1、单生产者-单消费者模型参考 C++实现生产者消费者模型 1、实现细节 具体的实现逻辑是构建一个queue来存储生产的数据,queue不满时可以生产,不...
  • 进程调度算法-生产者消费者问题

    千次阅读 2019-06-14 23:13:33
    @进程调度算法之生产者消费者问题 生产者消费者问题 问题介绍 生产者生产产品,消费者消费产品,两者的资源存储在同一个资源池。 因此,问题来了,生产者生产商品需要在资源池的存储范围内;然而消费者消费的资源...
  • 生产者消费者对缓冲区互斥访问是互斥关系,同时生产者消费者又是一个相互协作的关系,只有生产者生产之后,消费者只能才能消费,它们还是同步关系。 (2)、整理思路。只有生产生产者消费者进程,正好是这两个...
  •  一组生产者进程和一组消费者进程共享一个初始为空、大小为n的缓冲区,只有缓冲区没满时,生产者才能把消息放入缓冲区,否则必须等待;只有缓冲区不空时,消费者才能从中取出消息,否则只有等待。由于缓冲区是临界...
  • 生产者-消费者问题

    千次阅读 2018-03-28 19:04:43
    问题基本描述生产者消费者问题是一个著名的进程同步的问题。它描述的是:有一群生产者进程在生产产品,并将这些产品提供给消费者进程去消费。为使生产者进程与消费者进程能并发执行,在两者之间设置了一个具有n个...
  • 同步互斥问题 - 生产者消费者问题 问题描述: 有多个进程:多个生产者进程和多个消费者进程共享一个初始为空、固定大小为n的缓存(缓冲区)。生产者的工作是制造数据,只有缓冲区没满时,生产者才能把消息放入...
  • 生产者消费者问题c语言Here you will learn about producer consumer problem in C. 在这里,您将了解C语言中的生产者消费者问题。 Producer consumer problem is also known as bounded buffer problem. In this ...
  • 那个缓冲区的作用,求演示一下,还有,编程序的时候,我设定了信号量,PV原语,但是 不知道主函数输入什么,是输入生产或者消费等一系列动作么?它的互斥体现在哪
  • PV操作解决进程同步问题,生产者消费者问题为例

    千次阅读 多人点赞 2019-07-08 19:49:23
    所以在这种情况中,生产者消费者存在同步关系,而且各个生产者之间、各个消费者之间存在互斥关系,他们必须互斥地访问缓冲区。 解题如下: 定义四个信号量: empty——表示缓冲区是否为空,初值为n。 full...
  • [操作系统]生产者/消费者问题

    万次阅读 2018-04-13 21:32:47
    生产者/消费者问题也叫缓存绑定问题(bounded- buffer),是一个经典的、多进程同步问题。 单生产者和单消费者 仓库容量为一的情况 问题分析: 仓库有空位时,生产者才能生产产品,并放入仓库中; 仓库中...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 367,402
精华内容 146,960
关键字:

消费者生产者问题

友情链接: lecture12.rar