java 多线程学习之多生产者多消费者产生的线程安全问题分析与解决:Lock和Condition
来源:互联网 发布:qq群网络原因上传失败 编辑:程序博客网 时间:2024/05/17 21:37
//多生产者多消费者//这是一段会产生错误数据的示例class Resource { private String name; int count; boolean flag = false; public synchronized void produce(String name) { if (flag) { try { this.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } this.name = name + count; ++count; System.out.println(Thread.currentThread().getName()+"----" + name+count + "---"+" produced"); flag = true; notify(); } public synchronized void consume() { if (!flag) { try { this.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println(Thread.currentThread().getName() + name +count+ "consumed"); flag = false; notify(); }}class Producer implements Runnable { Resource r; public Producer(Resource r) { this.r = r; } @Override public void run() { while (true) { r.produce("烤鸭"); } }}class Consumer implements Runnable { Resource r; public Consumer(Resource r) { this.r = r; } @Override public void run() { while(true){ r.consume(); } }}public class ProducerConsumer { public static void main(String[] args) { Resource r=new Resource(); Producer producer=new Producer(r); Consumer consumer=new Consumer(r); Thread t0=new Thread(producer); Thread t1=new Thread(producer); Thread t2=new Thread(producer); Thread t3=new Thread(consumer); Thread t4=new Thread(consumer); Thread t5=new Thread(consumer); t0.start(); t1.start(); t2.start(); t3.start(); t4.start(); t5.start();
1.线程安全问题产生的原因:
当有一个生产线程开始执行的同时,有另外的生产线程和消费线程在被wait时,生产线程在run方法末尾随机唤醒一个进程,恰好唤醒了另一个生产线程,导致该生产线程在flag=true的情况下仍然可以生产
解决办法1:
- 将flag的if判断变成while循环判断,解决了线程获取执行权后是否应该执行的问题。
- 将notify改成notifyAll,如果本方唤醒了本方的线程,没有意义,而且while判断+notify会导致死锁。
但是这种方法开销很大,可能造成很多次无用的判断,降低效率
解决办法2:使用Lock和Condition
JDK1.5 以后将同步和锁封装成了对象,并将操作锁的隐式方法变成了显式的动作。
//显式锁的使用示例Lock lock =new ReentrantLock();lock.lock();try(){.....需要同步的代码块....}finally{lock.unlock();}
condition接口
子类对象可以由lock的方法获得,一个lock可以有多个condition对象。
1. await();
2. signal();
3. signalAll();
//示例Lock lock=new ReentrantLock();Condition cond=lock.newCondition();
使用lock和condition解决多生产者多消费者问题
package MultiThread;import java.util.concurrent.locks.Condition;import java.util.concurrent.locks.Lock;import java.util.concurrent.locks.ReentrantLock;/** * Created by lenovo on 2017/3/14. */class Item{ public int value; public Item(int value) { this.value = value; }}class Buffer { Lock lock = new ReentrantLock(); Condition notFull = lock.newCondition(); Condition notEmpty = lock.newCondition(); final int Max = 100; int putIndex=0; int takeIndex=0; int count = 0; final Item[] items = new Item[Max]; public void produce() { lock.lock(); try { while (count == Max) { try { notFull.await(); } catch (InterruptedException e) { e.printStackTrace(); } } Item x=new Item(putIndex); items[putIndex] = x; System.out.println(x.value+"has been produced"); if (++putIndex == Max) putIndex = 0; ++count; notEmpty.signal(); } finally { lock.unlock(); } } public Item consume() { lock.lock(); try { while (count == 0) { try { notEmpty.await(); } catch (InterruptedException e) { e.printStackTrace(); } } Item x = items[takeIndex]; System.out.println(x.value+"has been consumed"); if (++takeIndex == Max) takeIndex = 0; --count; notFull.signal(); return x; } finally { lock.unlock(); } }}class Producer implements Runnable { Buffer r; public Producer(Buffer r) { this.r = r; } @Override public void run() { while (true) { r.produce(); } }}class Consumer implements Runnable { Buffer r; public Consumer(Buffer r) { this.r = r; } @Override public void run() { while (true) { r.consume(); } }}public class ProducerConsumer { public static void main(String[] args) { Buffer r = new Buffer(); Producer producer = new Producer(r); Consumer consumer = new Consumer(r); Thread t0 = new Thread(producer); Thread t1 = new Thread(producer); Thread t2 = new Thread(producer); Thread t3 = new Thread(consumer); Thread t4 = new Thread(consumer); Thread t5 = new Thread(consumer); t0.start(); t1.start(); t2.start(); t3.start(); t4.start(); t5.start(); }}
**注意点:
1. lock.lock()和lock.unlcok()包围同步代码块
2.lock.unlock() 需要写在finally中,保证即使同步代码块中发生异常,unlock()仍会被执行。
3. 只需唤醒另一个监视器中的一个进程即可,不必signalAll()。**
0 0
- java 多线程学习之多生产者多消费者产生的线程安全问题分析与解决:Lock和Condition
- java多线程之多生产者与多消费者案例之Lock和Condition实现方式
- java多线程学习笔记(七) ——消费者与生产者(LOCK、Condition接口)
- 多线程——用Lock(锁)和Condition(监听器)来优化生产者消费者模式(进一步优化,解决可能产生的死锁问题)
- Java 多线程(三)线程间的通信jdk1.5中Lock,Condition---生产者消费者为例
- java学习笔记之多线程生产者与消费者
- 之生产者与消费者问题,Lock和Condition,线程面试题
- java之多线程实例 生产者与消费者
- java线程协作,经典生产者/消费者模式(二、Lock和Condition)
- Java SE学习笔记:线程通信、生产者与消费者案例、线程状态(线程的生命周期)、线程操作、Condition类
- 多线程-生产者消费者问题代码2并解决线程安全问题
- 使用 Lock 与Condition 实现生产者消费者
- 多线程之多消费者与生产者
- java多线程之多线程的线程安全问题
- 黑马程序员 利用Lock Condition解决多生产者多消费者问题的实例
- Lock和Condition实现阻塞队列与生产者消费者模式的实现
- java个人学习笔记19(多生产者多消费者+循环判断标记+notifyAll()+Lock+Condition)
- 使用Lock的Condition实现生产者消费者
- Linux配置apache+php+mysql
- ros_arduino_bridge的安装及使用
- python3.x 画图二维
- os.path模块简介
- JSP 日期处理
- java 多线程学习之多生产者多消费者产生的线程安全问题分析与解决:Lock和Condition
- 自定义密码输入EditTextLayout
- Animator 实现 FloatActionBar 点击弹出多个FloatActionBar
- Cloud云深网谈:空手套白狼的智慧
- [bzoj4293][PA2015]Siano
- 几何着色器
- uboot 通用board_init_f实现
- Wdate 小知识点
- 数据结构之链表