实习记录-Java实现生产者消费者问题
实习记录-Java实现生产者消费者问题
生产者消费者问题
- 经典多线程问题
生产者生产消息并存放入共享队列中,消费者从共享队列取得消息并且消费。
在多并发条件下对同一资源的控制,同时当缓存区空时,消费者阻塞,缓存区满时,生产者阻塞
解决方法
- 同步机制-锁和管道
1.通过wait和notify方法。利用对象(共享缓存区)锁和wait以及notify方法,条件不满足时wait挂起线程并释放锁,同时notify唤醒挂起线程。
2.通过await和signal方法。ReentrantLock和Condition的await和signal方法,不同的condition调用会使得唤醒线程不同。
3.通过BlockingQueue阻塞队列。阻塞队列自动在满时对生产者进行阻塞而在空时对消费者进行阻塞。
4.通过信号量Semaphore。需要生产者+消费者信号=实际缓冲区大小。同时需要设定额外一个以确保其同步
5.通过管道PipeInputStream和PipeOutputStream。connect对管道连接,仅适用于两个线程间通信。
实现方式:2-代码https://github.com/41503257/PACtest
引出的问题
-
为什么使用 while而不是if
线程唤醒后,再次轮到自身时需要继续判断条件是否符合,只有符合才能继续。即唤醒前后都需要判断其条件。
-
关于await方法做了什么事情,signal又做了什么事情
每个condition内部拥有等待队列(单链),每个lock有同步队列
condition调用await时,首先将本线程封装为node节点加入到condition的等待队列,通过fullyRelease释放锁(若无持有锁则抛异常。)在等待队列中, LockSupport.park阻塞当前节点。当前节点从阻塞中被唤醒(signalled or interrupted),则会从等待队列转移到同步队列(被动或主动地)在同步队列中,自旋获取锁成功。完成await方法
signal方法将等待队列的节点取出并加入同步队列,使其可以获取锁