zoukankan      html  css  js  c++  java
  • synchronized wait notify 生产者消费者

    1.生产者消费者模型

    public class ProducterConsumerTest{
        public static void main(String[] args){
            System.out.println("this is a test...");
            Message msg=new Message();
            Producter pro=new Producter(msg);
            Consumer con=new Consumer(msg);
            new Thread(pro).start();
            new Thread(con).start();
            new Thread(con).start();
        }
    }
    class Message {
        String title;
        String content;
    
        public synchronized void set(String title,String content){
            //问题1:while 还是 if
            while (this.content!=null){
                try{
                    this.wait();
                }catch(Exception exc){}
            }
            //模拟延迟
            try{
                Thread.sleep(100);
            }catch(Exception exc){}
            this.title=title;
            this.content=content;
            System.out.println(Thread.currentThread().getName()+"-生产:"+this.title+this.content);
            //问题2 notify 还是notifyAll
            super.notify();
        }
        public synchronized void get(){
            //问题1:while 还是 if
            while(this.content==null){
                try{
                    this.wait();
                }catch(Exception exc){}
            }
            //模拟延迟
            try{
                Thread.sleep(100);
            }catch(Exception exc){}
            System.out.println(Thread.currentThread().getName()+"-消费:"+this.title+this.content);
            this.title=null;
            this.content=null;
            //问题2 notify 还是notifyAll
            super.notify();
        }
    }
    class Producter implements Runnable {
        Message msg;
        public Producter(Message msg){
            this.msg=msg;
        }
        @Override
        public void run(){
    
            for(int i=0;i<10;i++){
    
                msg.set("华为"," Meate100");
            }
        }
    }
    class Consumer implements Runnable{
        Message msg;
        public Consumer(Message msg){
            this.msg=msg;
        }
        @Override
        public void run(){
            for(int i=0;i<5;i++){
                msg.get();
            }
        }
    }
    
    //运行结果(notifyAll()+while):
    this is a test...
    生产:华为 Meate100
    消费:华为 Meate100
    生产:华为 Meate100
    消费:华为 Meate100
    生产:华为 Meate100
    消费:华为 Meate100
    生产:华为 Meate100
    消费:华为 Meate100
    生产:华为 Meate100
    消费:华为 Meate100
    

    2.Entry Set(锁池)、Wait Set(等待池)

    对于Entry Set:如果线程A已经持有了对象锁,此时有其他线程也想获得该对象锁的话,它只能进入Entry Set,并且线程处于BLOCKED状态。

    对于Wait Set:如果线程A调用了wait()方法,那么线程A会释放该对象的锁,进入到Wait Set,并且线程处于WAITING状态。

    3.Wait、Notify、NotifyAll 、Entry Set(锁池)、Wait Set(等待池)画图说明

                    


                    


                    

    4.衍生出的问题

    A.用notify还是notifyAll:
    线程1-生产
    线程2-消费 -waiting
    线程3-消费 -waiting
    notify场景分析:
    步骤一:线程1生产完成后wait(),执行notify()随机唤醒一个是线程2,判断之后满足条件,进行消费,线程2消费完后wait(),执行notify().
    此时三个线程状态是
    线程1-waiting
    线程2-waiting-执行notify
    线程3-waiting

    步骤二:这是如果唤醒的是线程3,那么是不满足消费条件的,所以线程3继续wait(),而没有进行唤醒操作
    这是问题产生了
    线程1-waiting
    线程2-waiting
    线程3-waiting
    死锁、死锁、死锁了...

    如果我们用的是notifyAll(),那么步骤一线程2消费完成后,执行notifyAll(),结果是什么呢?
    (1)如果是线程1抢到锁,满足条件,进行生产,生产完成后notifyAll()
    (2)如果是线程3抢到锁,不满足条件,线程3wait(),释放锁,此时只有线程1是在锁池中,线程1会抢到锁,之后执行(1)

    so,notify会导致死锁问题,最好使用notifyAll()

    B.wait外层用while还是if:
    notifyAll下if运行结果:

    这里我没想明白,明明是同步方法为啥子会出现这个问题呢?
    或者
    就是当线程被wait之后进入等待队列,当被唤醒时,线程是继续往wait下面继续执行还是从synchronized monitor锁的地方再次执行?

    答案只有一个:
    上边的异常说明了->【wait被唤醒后,会继续往wait之后的代码执行而不是重新从monitor同步块处执行】 (这个结论是从代码运行推断,能力有限,没找到佐证,留待后续补充吧...........)
    附上JDK中的说明

    C.wait和synchronized绑定使用:
    同上图

    作者:往霄龙
    求其上者得其中,求其中者得其下
  • 相关阅读:
    求文件的hash值(基于SHA3的Hash)
    Discrete Log Algorithms :Baby-step giant-step 【二】
    非专业填坑
    xml转换csv
    使用PowerShell批量注册DLL到GAC
    ui-grid 中cellTemplate中click事件
    ui-grid样式,表格高度自适应行高,没有滚动条,去掉表头
    ui-grid使用详解
    数组过滤重复元素
    正则表达式验证邮箱
  • 原文地址:https://www.cnblogs.com/JQKA/p/11848304.html
Copyright © 2011-2022 走看看