# 代码:

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的更多相关文章

  1. 【多线程】--生产者消费者模式--Lock版本

    在JDK1.5发布后,提供了Synchronized的更优解决方案:Lock 和 Condition 我们使用这些新知识,来改进例子:[多线程]--生产者消费者模式--Synchronized版本 改 ...

  2. 多线程-生产者消费者(lock同步)

    二.采用Lock锁以及await和signal方法是实现 import java.io.IOException; import java.util.concurrent.locks.Condition ...

  3. 生产者消费者模式--阻塞队列--LOCK,Condition--线程池

    1.阻塞队列:http://www.cnblogs.com/dolphin0520/p/3932906.html 2.Condition 生产者消费者实现 :http://www.cnblogs.co ...

  4. 使用Lock锁生产者消费者模式

    package com.java.concurrent; import java.util.concurrent.locks.Condition; import java.util.concurren ...

  5. 并发、并行、同步、异步、全局解释锁GIL、同步锁Lock、死锁、递归锁、同步对象/条件、信号量、队列、生产者消费者、多进程模块、进程的调用、Process类、

    并发:是指系统具有处理多个任务/动作的能力. 并行:是指系统具有同时处理多个任务/动作的能力. 并行是并发的子集. 同步:当进程执行到一个IO(等待外部数据)的时候. 异步:当进程执行到一个IO不等到 ...

  6. Java 多线程之生产者消费者(多个生成者多个消费者)synchronized 和lock多线程通讯和同步实现

    public class ProducterConsumerSample { public static void main(String[] args) { Resourse res = new R ...

  7. 7.生产者消费者 案例 (使用Lock 同步锁 方式,使用Condition完成线程之间的通信)

    /* * 生产者消费者 案例 (使用Lock 同步锁 方式,使用Condition完成线程之间的通信) * */ public class TestProductorAndConsumerForLoc ...

  8. Lock之ReentrantLock及实现生产者消费者和死锁

    Lock是顶层接口,它的实现逻辑并未用到synchronized,而是利用了volatile的可见性.ReentrantLock对了Lock接口的实现主要依赖了Sync,而Sync继承了 Abstra ...

  9. 线程高级篇-Lock锁实现生产者-消费者模型

    Lock锁介绍: 在java中可以使用 synchronized 来实现多线程下对象的同步访问,为了获得更加灵活使用场景.高效的性能,java还提供了Lock接口及其实现类ReentrantLock和 ...

随机推荐

  1. Lua易忘点

    仅针对自己 __index的理解 __index是:当我们访问一个表中的元素不存在时,则会触发去寻找__index元方法,如果不存在,则返回nil,如果存在,则返回结果 Window = {} Win ...

  2. 抄录的Linux命令

    daemon daemon 有一个很高大上的中文名字,叫 守护进程 . 有句话是这么说的,如果 Unix 中没有了守护进程,那么 Unix 就不会是相同的. 它很有个性,是一个运行在后台且不受终端控制 ...

  3. ZOJ Problem Set - 1003

    1.翻译参考 http://www.cnblogs.com/woodfish1988/archive/2006/11/10/556926.html 2.代码参考 http://www.cnblogs. ...

  4. zping ping包工具20180605.exe测试版

    链接: https://pan.baidu.com/s/1WB3BZn0r9n4DRU_8bNC65g 提取码: mybi zping的第一个exe版本由于未对兼容性进行测试,使用python3.6编 ...

  5. java分词工具hanlp介绍

    前几天(6月28日),在第23届中国国际软件博览会上,hanlp这款自然语言处理工具荣获了“2019年第二十三届中国国际软件博览会优秀产品”. HanLP是由一系列模型预算法组成的工具包,结合深度神经 ...

  6. MySQL+navicat-1064 Error解决方案

    MySQL+navicat-1064 Error解决方案 错误 #1064 - You have an error in your SQL syntax; check the manual that ...

  7. Spring4学习回顾之路07- 通过工厂方法配置Bean

    一:通过静态工厂配置Bean 建立Student.java package com.lql.srping04; /** * @author: lql * @date: 2019.10.28 * Des ...

  8. rbac权限控制组件实现控制的基本原理图

    今天先整理一个rbac的权限控制的原理图上来 代码 后面就不透漏了,但是实现的方法有很多种,我这个只是其中一种的一部分!

  9. Java反射的理解(六)-- 通过反射了解集合泛型的本质

    Java反射的理解(六)-- 通过反射了解集合泛型的本质 上述写了那么多,我们可能会有个疑问,为什么要用反射,步骤比我们常规的加载类操作复杂多了,别急,这个问题我最后才解答,我们先来了解集合泛型的本质 ...

  10. Visual Studio 2012网站如何只生成一个DLL文件

    简介: 在Visual Studio 2005,2008,2010版本中,都有Web Deployment工具将网站进行发布,所有代码文件和库文件发布,生成为一个动态链接库文件,而在Visual St ...