高并发编程-使用wait和notifyAll进行线程间的通信3_多线程下的生产者消费者模型和notifyAll

简介: 高并发编程-使用wait和notifyAll进行线程间的通信3_多线程下的生产者消费者模型和notifyAll

20191031000606569.png


概述

高并发编程-线程通信_使用wait和notify进行线程间的通信2_多生产者多消费者导致程序假死原因分析 中分析了假死的原因,这里我们来看下改如何解决在多线程下出现的这个问题呢?

20191008232746942.png

解决办法

  1. 多线程情况用while而不是if 来判断条件是否满足
  2. notify —> notifyAll
package com.artisan.test;
import java.util.stream.Stream;
public class MultiProduceConsumerDemo2 {
    // 对象监视器-锁
    private final Object LOCK = new Object();
    // 是否生产出数据的标识
    private boolean isProduced = false;
    // volatile 确保可见性, 假设 i 就是生产者生产的数据
    private volatile int i = 0;
    public void produce() {
        synchronized (LOCK) {
            String msg = isProduced ? "已生产货物" : "没有货物可搬运";
            // while 每次被唤醒时都会先检查isProduced是否滿足條件再继续
            // 不能用if的原因:if它将不再判断isProduced是否滿足條件,直接继续,引发错误
            // 举个例子 t1 ,t2 都进入到了wait ,然后使用if, 唤醒了t2后,不再判断isProduced是否滿足條件
            // 直接又生产了一个,导致生产多了数据
            while (isProduced) {
                try {
                    System.out.println(Thread.currentThread().getName() + " GOT LOCK ,isProduced= " + isProduced + " wait becauseof  " + msg);
                    LOCK.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            i++;
            System.out.println(Thread.currentThread().getName() + " GOT LOCK ,isProduced= " + isProduced + " Produce:" + i);
            // 唤醒所有正在等待这个对象的monitor的线程
            LOCK.notifyAll();
            isProduced = true;
        }
    }
    public void consume() {
        // 加锁
        synchronized (LOCK) {
            String msg = isProduced ? "已生产货物" : "没有货物可搬运";
            // while 每次被唤醒时都会先检查isProduced是否滿足條件再继续
            while (!isProduced) {
                try {
                    System.out.println(Thread.currentThread().getName() + " wait becauseof  " + msg);
                    LOCK.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.println(Thread.currentThread().getName() + " GOT LOCK ,isProduced= " + isProduced + " Consume:" + i);
            //唤醒所有正在等待这个对象的monitor的线程
            LOCK.notifyAll();
            isProduced = false;
        }
    }
    public static void main(String[] args) {
        MultiProduceConsumerDemo2 produceConsumerDemo = new MultiProduceConsumerDemo2();
        Stream.of("P1", "P2").forEach(n -> new Thread(n) {
            @Override
            public void run() {
                while (true) produceConsumerDemo.produce();
            }
        }.start());
        Stream.of("C1", "C2").forEach(n -> new Thread(n) {
            @Override
            public void run() {
                while (true) produceConsumerDemo.consume();
            }
        }.start());
    }
}


相关文章
|
2天前
|
设计模式 消息中间件 安全
【Java多线程】关于多线程的一些案例 —— 单例模式中的饿汉模式和懒汉模式以及阻塞队列
【Java多线程】关于多线程的一些案例 —— 单例模式中的饿汉模式和懒汉模式以及阻塞队列
9 0
|
2天前
|
Java 数据库
【Java多线程】对线程池的理解并模拟实现线程池
【Java多线程】对线程池的理解并模拟实现线程池
10 1
|
2天前
|
Java
【Java多线程】分析线程加锁导致的死锁问题以及解决方案
【Java多线程】分析线程加锁导致的死锁问题以及解决方案
11 1
|
2天前
|
存储 缓存 安全
【Java多线程】线程安全问题与解决方案
【Java多线程】线程安全问题与解决方案
9 1
|
2天前
|
Java 调度
【Java多线程】线程中几个常见的属性以及状态
【Java多线程】线程中几个常见的属性以及状态
8 0
|
2天前
|
Java 调度
【Java多线程】对进程与线程的理解
【Java多线程】对进程与线程的理解
10 1
|
4天前
|
存储 安全 Java
【探索Linux】P.21(多线程 | 线程同步 | 条件变量 | 线程安全)
【探索Linux】P.21(多线程 | 线程同步 | 条件变量 | 线程安全)
10 0
|
5月前
|
Java
在高并发环境下,再次认识java 锁
在高并发环境下,再次认识java 锁
38 0
|
5月前
|
消息中间件 NoSQL Java
Java高级开发:高并发+分布式+高性能+Spring全家桶+性能优化
Java高架构师、分布式架构、高可扩展、高性能、高并发、性能优化、Spring boot、Redis、ActiveMQ、Nginx、Mycat、Netty、Jvm大型分布式项目实战学习架构师之路
|
24天前
|
存储 NoSQL Java
探索Java分布式锁:在高并发环境下的同步访问实现与优化
【4月更文挑战第17天】Java分布式锁是解决高并发下数据一致性问题的关键技术,通过Redis、ZooKeeper、数据库等方式实现。它确保多节点共享资源时的同步访问,防止数据不一致。优化策略包括锁超时重试、续期、公平性和性能优化。合理设计分布式锁对支撑大规模分布式系统至关重要。