首页 > 其他 > 详细

多Product多Consumer之间的通讯导致出现程序假死的原因分析

时间:2020-09-06 20:40:05      阅读:91      评论:0      收藏:0      [点我收藏+]

多Product多Consumer之间的通讯导致出现程序假死的原因分析

继续上篇文章,我们来吧单个生产者消费者改成多个生产者消费者,这里使用java8的Stream,代码如下:

/**
 * @program: ThreadDemo
 * @description: 线程通信(生产者-消费者)
 * @author: hs96.cn@Gmail.com
 * @create: 2020-09-06
 */
public class ProduceConsumerVersion2 {
    private int i = 0;
    private final Object LOCK = new Object();
    /**
     * 是否已经消费
     */
    private volatile boolean isProduced = false;

    public void produce() {
        synchronized (LOCK) {
            if (isProduced) {
                try {
                    LOCK.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            } else {
                System.out.println("P->" + (++i));
                LOCK.notify();
                isProduced = true;
            }
        }
    }

    public void consume() {
        synchronized (LOCK) {
            if (isProduced) {
                System.out.println("C->" + i);
                LOCK.notify();
                isProduced = false;
            } else {
                try {
                    LOCK.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    public static void main(String[] args) {
        ProduceConsumerVersion2 pc = new ProduceConsumerVersion2();

        // 多个生产者、消费者线程运行时,会产生一些问题
        Stream.of("P1", "P2").forEach(n ->
                new Thread(() -> {
                    while (true) {
                        pc.produce();
                    }
                }, n).start()
        );
        Stream.of("C1", "C2").forEach(n ->
                new Thread(() -> {
                    while (true) {
                        pc.consume();
                    }
                }, n).start()
        );
    }
}

运行效果如下:
技术分享图片

可以看到阻塞了,那么是不是有死锁了呢,jstack来查一下:
技术分享图片

可以看到没有死锁,那是为什么会卡住呢?下面增加一些调试语句用来定位跟踪,我把代码贴出来,有兴趣的朋友在大脑里分析一下,本地再执行一下验证自己的想法,代码如下:

public class ProduceConsumerVersion2 {
    private int i = 0;
    private final Object LOCK = new Object();
    /**
     * 是否已经消费
     */
    private volatile boolean isProduced = false;

    public void produce() {
        synchronized (LOCK) {
            if (isProduced) {
                try {
                    System.out.println(Thread.currentThread().getName() + "wait了");
                    LOCK.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            } else {
                i++;
                System.out.println(Thread.currentThread().getName() + "生产了->" + i);
                LOCK.notify();
                System.out.println(Thread.currentThread().getName() + "notify了" + i);
                isProduced = true;
            }
        }
    }

    public void consume() {
        synchronized (LOCK) {
            if (isProduced) {
                System.out.println(Thread.currentThread().getName() + "消费了->" + i);
                LOCK.notify();
                System.out.println(Thread.currentThread().getName() + "notify了");
                isProduced = false;
            } else {
                try {
                    System.out.println(Thread.currentThread().getName() + "wait了");
                    LOCK.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    public static void main(String[] args) {
        ProduceConsumerVersion2 pc = new ProduceConsumerVersion2();

        // 多个生产者、消费者线程运行时,会产生一些问题
        Stream.of("P1", "P2").forEach(n ->
                new Thread(() -> {
                    while (true) {
                        pc.produce();
                    }
                }, n).start()
        );
        Stream.of("C1", "C2").forEach(n ->
                new Thread(() -> {
                    while (true) {
                        pc.consume();
                    }
                }, n).start()
        );
    }
}

运行效果如下:
技术分享图片

可以看到P1,C1,P2,C2都wait了,然后程序就假死了,这是什么原因呢?

这里我就不一步一步分析了,这里只需要明白一个道理即可,当有多个wait的时候,notify是随机的。这个我们后续再探讨,先吃个饭~

多Product多Consumer之间的通讯导致出现程序假死的原因分析

原文:https://www.cnblogs.com/stormsquirrel/p/13623274.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!