一、背景 && 定义
多线程环境下,只要有并发问题,就要保证数据的安全性,一般指的是通过 synchronized 来进行同步。
另一个问题是, 多个线程之间如何协作呢 ?
我们看一个仓库出货问题(更具体一些,快餐店直接放好炸货的架子,不过每次只放一份)
假设仓库中只能存放一件商品,生产者将生产出来的产品放入仓库,消费者将仓库中产品取走进行消费;
如果仓库中没有商品,那么生产者将产品放入仓库,否则停止生产并等待,直到仓库中的产品被消费者取走为止;
如果仓库中放有产品,消费者可快速取走并消费,否则停止消费并等待,直到仓库中再次放入产品为止。
这其实就是一个线程同步问题。 生产者和消费者共享同一个资源,并且生产者和消费者之间互相依赖,互为条件。
如果一个快餐店:
先点单,餐出来之后再收钱。这种模式叫BIO-阻塞IO模式。
如果一个快餐店:
先收钱,收完钱消费者在旁边等。这种就是生产者-消费者模式。
这类问题里,同步的候只有 synchronized 是不够的,因为他虽然能解决资源的共享问题,实现资源的同步更新,但是无法 在不同线程之间进行消息传递 (通信)。
所以只有我们之前所说的 加锁 和 排队 是不够的,还要有 通知 。
定义:
生产者和消费者在同一时间段内共用同一个存储空间,生产者往存储空间中添加产品,消费者从存储空间中取走产品,当存储空间为空时,消费者阻塞,当存储空间满时,生产者阻塞。
为了解决双方能力不等而等待的问题,引入对应的解决方案。生产者消费者模型是一种并发协作模型。
二、解决方式介绍
2.1 管程法
生产者 :负责生产数据的模块(模块可能是方法、对象、线程、进程);
消费者 :负责处理数据的模块(模块可能是方法、对象、线程、进程);
缓冲区 :消费者不能直接使用生产者的数据,它们之间有个“缓冲区”(缓冲区一般是队列)。
生产者和消费者都是通过缓冲区进行数据的 放 和 那 。
这样的话,一来可以避免旱的旱死,涝的涝死的问题:不管哪一方过快或者过慢,缓冲区始终有一部分数据;二来能够达到生产者和消费者的解耦,不再直接通信,从而提高效率。
因为容器相当于一个输送商品的管道,所以成为 管程法 。
2.2 信号灯法
采用类似红灯绿灯的模式