Java线程之1.4版多生产多消费者示例(三)

来源:互联网 发布:oracle数据触发器 编辑:程序博客网 时间:2024/06/05 08:46

多生产者,多消费者

从单生产者单消费者示例进化而来

注意两个变化的地方:

  • 为判断标记任务循环体的if—->while
  • 为避免死锁唤醒notify–>notifyAll

  1. 分析下(if+notifty)的安全隐患

    • tp0先开锁获取CPU执行权 生产:1 然后flag=true, 唤醒进程缓冲池(),退出
    • 然后如果tp0,tp1再获得CPU执行资格,但是判断flag=true,进入缓冲池(tp0,tp1)
    • 然后tc0获取CPU执行权,消费:1 然后flag=false,唤醒缓冲池(tp0,tp1),退出,假设唤醒的tp1
    • 然后假如tc0,tc1想获取执行资格,判断flag = false,进入缓冲池(tp0,tc0,tc1)
    • 此时已经唤醒的tp1并不会再去判断flag标识,继续向下执行,那么就出现了多生产无消费的情况

    同理,1生产多消费的情况也可能发生
    这里写图片描述

  2. 如果是按照单线程(while+notify)来

    • 假如tp0先开锁获取CPU执行权 生产:1 然后flag=true, 唤醒进程缓冲池(),退出
    • 然后如果tp0,tp1再获得CPU执行资格,但是判断flag=true,进入缓冲池(tp0,tp1)
    • 然后tc0获取CPU执行权,消费:1 然后flag=false,唤醒缓冲池(tp0,tp1),退出,假设唤醒的tp1
    • 然后假如tc0,tc1想获取执行资格,判断flag = false,进入缓冲池(tp0,tc0,tc1)
    • 然后假如tp1执行,生产:2 同样flag=true ,
    • 假如唤醒缓冲池中的是tp0而不是消费者tc0或者tc1,那么tp0和tp1判断后也会wait,这样最后4个进程都没有notify来唤醒,进入死锁

将if()改为while后可以让进程在wait后醒来再次判断flag

notifyAll可以避免出现死锁,但是会造成效率低下

*/

class Resource{    String name;    private int count = 1;    String id ;    private boolean flag = false;//初始默认没有产品    public synchronized void producer(String name)    {        while(flag)            try{wait();} catch (InterruptedException ex){}        this.name = name;        id = name + count++;        System.out.println(Thread.currentThread().getName()+"--->生产:"+id);        flag = true;        notifyAll();    }    public synchronized void consumer()    {        while(!flag)            try{wait();} catch (InterruptedException ex){}        System.out.println(Thread.currentThread().getName()+"--------->消费"+id);        flag = false;        notifyAll();    }}class Producer implements Runnable{    Resource r;    Producer(Resource r)    {        this.r = r;    }    public void run()    {        while(true)        {            r.producer("包子");        }    }}class Consumer implements Runnable{    Resource r;    Consumer(Resource r)    {        this.r = r;    }    public void run()    {        while (true)        {            r.consumer();        }    }}class ThreadPC2{    public static void main(String[] args)     {        //创建资源        Resource r = new Resource();        //创建线程任务        Producer p0 = new Producer(r);        Producer p1 = new Producer(r);        Consumer c0 = new Consumer(r);        Consumer c1 = new Consumer(r);        //创建线程        Thread tp0 = new Thread(p0);        Thread tp1 = new Thread(p1);        Thread tc0 = new Thread(c0);        Thread tc1 = new Thread(c1);        //开启线程        tp0.start();        tp1.start();        tc0.start();        tc1.start();    }}

结果:

1 0
原创粉丝点击