生产者消费者问题--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和 ...
随机推荐
- maven-插件地址
Maven官方有两个插件列表, 第一个列表的GroupId 为 org.apache.maven.plugins,这里的插件最为成熟,具体地址为:http://maven.apache.org/plu ...
- bash-2 httpd服务的源码编译安装脚本
httpd服务的源码编译安装脚本 #!/bin/bash # #******************************************************************** ...
- lamp的动静分离部署
一.lamp分离部署工作图 二.LAMP的安装与配置 1.环境准备 2.对 PHP 服务器进行部署 #以下为安装PHP及其依赖 [root@php ~ ]# .tar.gz -C /usr/src [ ...
- vue加scoped后无法修改样式(无法修改element UI 样式)
有的时候element提供的默认的样式不能满足项目的需要,就需要我们队标签的样式进行修改,但是发现修改的样式不起作用 第一种方法 原因:scoped 解决方法:去掉scoped 注意:此时该样式会污染 ...
- PYTHON 100days学习笔记006:函数和模块的使用
目录 Day006:函数和模块的使用 1.函数的作用 2.定义函数 2.1 语法 2.2 实例 2.3 函数的调用 4.函数的参数 4.1 必须参数 4.2 关键字参数 4.3 默认参数 4.4 不定 ...
- Linux下nginx配置https协议访问的方法
一.配置nginx支持https协议访问,需要在编译安装nginx的时候添加相应的模块--with-http_ssl_module 查看nginx编译参数:/usr/local/nginx/sbin/ ...
- 阿里云服务器安装svn完整步骤,避免新手可能出现的所有错误
centos6.8,没有安装svn的情况: 1.安装: yum install subversion (这一步一般不会错) 2.创建svn版本库: cd /root mkdir -p svn/proj ...
- python-文件常用操作
文件内建函数和方法: open()——打开文件 read()——输入 readline()——输入一行 seek()——文件内移动 write()——输出 close()——关闭文件 练习:
- Springmvc使用注解实现执行定时任务(定时器)
1.在Spring配置文件中添加 <task:annotation-driven/> 2.在需要调用执行定时任务的类中使用注解 @Service @Lazy(false) //避免spri ...
- CentOS7下使用ELK搭建日志集中分析平台
应用场景: ELK实际上是三个工具的集合,ElasticSearch + Logstash + Kibana,这三个工具组合形成了一套实用.易用的监控架构,很多公司利用它来搭建可视化的海量日志分析平台 ...