生产者消费者问题--lock
# 代码:
public class App {
public static void main(String[] args) {
Depot depot = new Depot(100);
Producer producer = new Producer(depot);
Consumer consumer = new Consumer(depot);
producer.produce(60);
consumer.consume(100);
producer.produce(90);
consumer.consume(40);
}
}
class Producer {
private Depot depot;
public Producer(Depot depot) {
this.depot = depot;
}
public void produce(final int val) {
new Thread() {
public void run() {
depot.produce(val);
}
}.start();
}
}
class Consumer {
private Depot depot;
public Consumer(Depot depot) {
this.depot = depot;
}
public void consume(final int val) {
new Thread() {
public void run() {
depot.consume(val);
}
}.start();
}
}
class Depot {
private int capacity;
private int size;
private Lock lock;
private Condition fullCondition;
private Condition emptyCondition;
public Depot(int capacity) {
this.size = 0;
this.capacity = capacity;
this.lock = new ReentrantLock();
fullCondition = lock.newCondition();
emptyCondition = lock.newCondition();
}
public void produce(int val) {
lock.lock();
try {
int surplus = val;
while (surplus > 0) {
while (size >= capacity) {
fullCondition.await();
}
int incre = (size + surplus) > capacity ? (capacity - size) : surplus;
size += incre;
surplus -= incre;
System.out.printf("%s plan to produce (%d), actually produce (%d), depot size (%d) \n",
Thread.currentThread().getName(), val, incre, size);
emptyCondition.signal();
}
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
public void consume(int val) {
lock.lock();
try {
int surplus = val;
while (surplus > 0) {
while (size <= 0) {
emptyCondition.await();
}
int desc = (size < surplus) ? size : surplus;
size -= desc;
surplus -= desc;
System.out.printf("%s plan to consume (%d), actutally consume (%d), depot size (%d) \n",
Thread.currentThread().getName(), val, desc, size);
fullCondition.signalAll();
}
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
}
# 输出:
Thread-0 plan to produce (60), actually produce (60), depot size (60)
Thread-1 plan to consume (100), actutally consume (60), depot size (0)
Thread-2 plan to produce (90), actually produce (90), depot size (90)
Thread-3 plan to consume (40), actutally consume (40), depot size (50)
Thread-1 plan to consume (100), actutally consume (40), depot size (10)
# 有四个线程参与了这个过程,两个生产者,两个消费者
# 这是几个月之后的补充。。。。。。。。手动笑哭。
# 几个月之后,我重新回顾了这些内容。。。发现了上面的代码有坑!!!
# 首先我们来重现此坑
public static void main(String[] args) {
Depot depot = new Depot(100);
Producer producer = new Producer(depot);
Consumer consumer = new Consumer(depot);
for (int i = 0; i < 10; i++) {
producer.produce(50);
}
for (int i = 0; i < 50; i++) {
consumer.consume(10);
}
}
- main 方法是这个样子,在这种情况下,有时候会出现程序卡住的情况
- 用jstack看了一下堆栈信息,发现有几个consumer线程一直处于locked状态,但是已经没有人去唤醒他们了
- 分析了一下,其实原因很明显,我们在produce时,唤醒consumer使用的是signal(),最后一个生产者在唤醒某一个消费者之后,该消费者消费完了就再也没有生产者了,这时剩下的消费者线程就没有人唤醒他们了。。。换成signalAll()就ok了。
# 还有一个需要注意的是进入 await()的判断条件一定要使用while, 尽量不要使用if, 这个问题我会在 synchronized 实现的生产者-消费者模块中给出原因
生产者消费者问题--lock的更多相关文章
- 【多线程】--生产者消费者模式--Lock版本
在JDK1.5发布后,提供了Synchronized的更优解决方案:Lock 和 Condition 我们使用这些新知识,来改进例子:[多线程]--生产者消费者模式--Synchronized版本 改 ...
- 多线程-生产者消费者(lock同步)
二.采用Lock锁以及await和signal方法是实现 import java.io.IOException; import java.util.concurrent.locks.Condition ...
- 生产者消费者模式--阻塞队列--LOCK,Condition--线程池
1.阻塞队列:http://www.cnblogs.com/dolphin0520/p/3932906.html 2.Condition 生产者消费者实现 :http://www.cnblogs.co ...
- 使用Lock锁生产者消费者模式
package com.java.concurrent; import java.util.concurrent.locks.Condition; import java.util.concurren ...
- 并发、并行、同步、异步、全局解释锁GIL、同步锁Lock、死锁、递归锁、同步对象/条件、信号量、队列、生产者消费者、多进程模块、进程的调用、Process类、
并发:是指系统具有处理多个任务/动作的能力. 并行:是指系统具有同时处理多个任务/动作的能力. 并行是并发的子集. 同步:当进程执行到一个IO(等待外部数据)的时候. 异步:当进程执行到一个IO不等到 ...
- Java 多线程之生产者消费者(多个生成者多个消费者)synchronized 和lock多线程通讯和同步实现
public class ProducterConsumerSample { public static void main(String[] args) { Resourse res = new R ...
- 7.生产者消费者 案例 (使用Lock 同步锁 方式,使用Condition完成线程之间的通信)
/* * 生产者消费者 案例 (使用Lock 同步锁 方式,使用Condition完成线程之间的通信) * */ public class TestProductorAndConsumerForLoc ...
- Lock之ReentrantLock及实现生产者消费者和死锁
Lock是顶层接口,它的实现逻辑并未用到synchronized,而是利用了volatile的可见性.ReentrantLock对了Lock接口的实现主要依赖了Sync,而Sync继承了 Abstra ...
- 线程高级篇-Lock锁实现生产者-消费者模型
Lock锁介绍: 在java中可以使用 synchronized 来实现多线程下对象的同步访问,为了获得更加灵活使用场景.高效的性能,java还提供了Lock接口及其实现类ReentrantLock和 ...
随机推荐
- centos 设置dns
- OpenCV图像平移
图像平移是将图像的所有像素坐标进行水平或垂直方向移动,也就是所有像素按照给定的偏移量在水平方向上沿x轴.垂直方向上沿y轴移动.这种操作分为两种,一种是图像大小不改变,这样最后原图像中会有一部分不在图像 ...
- 根据文本内容确定UILabel的高度
NSString *str = @"严重依赖中国的美国公司包括苹果.百胜餐饮集团都感受到了近期人民币贬值带来的痛.这直接导致了苹果股价下跌了5.2%,拥有肯德基.必胜客的百胜也下跌了4.9% ...
- HTTP 状态代码的完整列表
1xx(临时响应) 用于表示临时响应并需要请求者执行操作才能继续的状态代码. 代码 说明 100(继续) 请求者应当继续提出请求.服务器返回此代码则意味着,服务器已收到了请求的第一部分,现正在等待接收 ...
- C# MVC MVP
https://www.codeproject.com/Articles/613682/Your-first-program-using-MVC-pattern-with-Csharp-W https ...
- Jenkins学习指南
jenkinshttps://www.cnblogs.com/jimmy-xuli/p/9020825.htmlhttps://www.cnblogs.com/along21/p/10172855.h ...
- 关于mac配置vs code的C++环境问题
在配置完成后,编译通过了但是在终端输出一直不出现很奇怪,求问大家这是啥问题 以下是我的配置
- [SDOI2008]石子合并 题解
题面 GarsiaWachs算法专门解决石子合并问题: 设一个序列是A[0..n-1],每次寻找最小的一个满足A[k-1]<=A[k+1]的k,那么我们就把A[k]与A[k-1]合并,并向前寻找 ...
- 并不对劲的复健训练-CF1205B Shortest Cycle
题目大意 有\(n\)(\(n\leq 10^5\))个数\(a_1,...,a_n\)(\(a\leq 10^{18}\)).有一个图用这个方法生成:若\(a_i\)按位与\(a_j\)不为0,则在 ...
- 《深入理解 Java 虚拟机》学习笔记 -- 内存区域
<深入理解 Java 虚拟机>学习笔记 -- 内存区域 运行时数据区域 主要分为 6 部分: 程序计数器 虚拟机栈 本地方法栈 Java 堆 方法区 如图所示: 1. 程序计数器(线程私有 ...