(52)多个生产者多个消费者出现的问题,解决方式synchronized方法和Lock方法
来源:互联网 发布:访问网站出现 php探针 编辑:程序博客网 时间:2024/06/05 04:51
public class Resoure { private String name; private int count =1; private boolean flag=false; public synchronized void set(String name) { if(flag) { try { this.wait(); } catch (Exception e) { } } this.name=name+"----"+count++; System.out.println(Thread.currentThread().getName()+"生产者"+this.name); flag=true; this.notify(); } public synchronized void out() { if (!flag) { try { this.wait(); } catch (Exception e) { } } System.out.println(Thread.currentThread().getName()+"消费者"+this.name); flag=false; this.notify(); } }public class Producer implements Runnable { private Resoure res; Producer(Resoure res){ this.res=res; } public void run() { while(true) { res.set("+商品+"); } }}public class Consumer implements Runnable { private Resoure res; Consumer(Resoure res){ this.res=res; } public void run() { while(true) { res.out(); } }}public class ProduceConsumerDemo { public static void main(String[] args) { Resoure r=new Resoure(); Producer pro=new Producer(r); Consumer con=new Consumer(r); Thread t1=new Thread(pro); Thread t2=new Thread(con); t1.start(); t2.start(); }}
两个生产者两个消费者,这个程序会出现问题:
t1线程开启,flag=false,所以生产了一个数据,将flag置为true,唤醒该对象的其他线程,t1可能还有执行权,所以继续执行,flag=true,等待,放弃资格。
其他当前对象的t2,t3,t4都有可能抢到资源。假设t2抢到了资源,因为flag是个共享资源,所以flag为真,等待放弃资格。
t3线程获得资格,if判断失败,即有数据可消费,所以消费,flag=false
唤醒t1。(正常消费),t3可能还可以执行,但if判断失败,所以等待,放弃执行资格.
假设此时t4此时获得了执行权,因为if判断失败,等待,放弃执行资格。
就只剩t1有执行资格,T1有执行资格,所以生产一个数据,flag=true,唤醒该对象的其他线程,t1仍有执行权,if判断失败放弃资格。此时,它唤醒的是t2(才会出现两个生产打印,只消费第一个情况),t2获取资格,此时,只有t2可以获得执行权,所以应从刚才等待的下一条语句开始执行,所以又生产了一个数据。
生产两个数据,第一个生产的数据被覆盖,输出的就是第二个数据。
为什么会出现这种情况呢?
原因是t1生产完后,将flag=true,理应t2不能生产,但是t1生产完后,可以唤醒t2,就不再判断if(flag),直接生产.
修改方法:
让这种情况消失需要修改的地方是将if(flag)改为while(flag),即使醒了,因为while,也会判断flag.
但是呢,这样做,会造成全睡的情况,全部等待,刚才就是只有t2获得资格,但是flag判断失败,所以全没资格了。但不是死锁。
死锁是锁中有异锁。
继续修改:
唤醒所有,将this.notify(),改为this.notifyall(),这样t2,t3,t4全唤醒,t2中while判断失败,失去资格。t3,t4虽然会都醒,但是只能一个线程有执行权,假设t3获得执行权,while(!flag)假,消费数据,
然后flag=false,t4又没有执行条件了。
通过Lock对此程序进行修改和以上的修改,就是表达方式不同
import java.util.concurrent.locks.*;public class Resoure { private String name; private int count =1; private boolean flag=false; private Lock lock=new ReentrantLock(); private Condition condition=lock.newCondition(); public void set(String name)throws InterruptedException { lock.lock(); try { while(flag) condition.await(); this.name=name+"----"+count++; System.out.println(Thread.currentThread().getName()+"生产者"+this.name); flag=true; condition.signalAll(); } finally { lock.unlock(); } } public void out()throws InterruptedException { lock.lock(); try { while (!flag) condition.await(); System.out.println(Thread.currentThread().getName()+"消费者"+this.name); flag=false; condition.signalAll(); } finally { lock.unlock(); } }}
上面的方法无论是signalAll,还是notifyAll都是唤醒其他等待的,可以支持多个相关的 Condition 对象,所以生产者可以唤醒消费者,互相唤醒。
**jdk1.5中提供了多线程升级解决方案。
将同步synchronized替换成现实Lock操作。
将Object中的wait,notify,notifyAll替换成Condition对象,该对象可以Lock锁,进行获取。**
import java.util.concurrent.locks.*;public class Resoure { private String name; private int count =1; private boolean flag=false; private Lock lock=new ReentrantLock(); private Condition condition_pro=lock.newCondition(); private Condition condition_con=lock.newCondition(); public void set(String name)throws InterruptedException { lock.lock(); try { while(flag) condition_pro.await(); this.name=name+"----"+count++; System.out.println(Thread.currentThread().getName()+"生产者"+this.name); flag=true; condition_con.signalAll(); } finally { lock.unlock(); } } public void out()throws InterruptedException { lock.lock(); try { while (!flag) condition_con.await(); System.out.println(Thread.currentThread().getName()+"消费者"+this.name); flag=false; condition_pro.signalAll(); } finally { lock.unlock(); } }}
- (52)多个生产者多个消费者出现的问题,解决方式synchronized方法和Lock方法
- 生产者消费者模型(多个生产者和多个消费者)JDK1.5 (Lock&Condition)实现版
- 生产者消费者--多个线程出现的问题
- 生产者消费者--多个线程出现的问题
- 多个生产者与多个消费者的问题
- 一个生产者多个消费者问题
- synchronized与Lock 的区别&分别实现生产者/消费者问题
- JAVA多线程(五)用lock、synchronized、阻塞队列三种方法实现生产者消费者模式
- 生产者和消费者(资源数目多个)
- 黑马程序员 利用Lock Condition解决多生产者多消费者问题的实例
- 生产者消费者模型(多个生产者和多个消费者)JDK1.5之前实现版
- 多个生产者,多个消费者
- 多生产者多消费者问题(Lock接口、Condition接口)
- C++之多个生产者与多个消费者的多线程问题
- day11多线程的安全问题-同步(技术锁)-多个生产者和消费者
- java lock await方法会释放掉当前锁 标准的生产者消费者问题
- java多线程 一个生产者和多个消费者
- Java多线程 9 多个生产者和消费者
- 变换元素transform的那些事儿
- 机器学习路线图
- android:imeOptions属性详解以及无效处理
- HDU 1394:Minimum Inversion Number
- IT之路-进制、运算符、控制语句-ZCSDN.2017.7.13
- (52)多个生产者多个消费者出现的问题,解决方式synchronized方法和Lock方法
- JackSon将json串转成List<Object>,异常com.fasterxml.jackson.databind.JsonMappingException
- faceDetection对比实验
- 关于File.ReadAllText Method (String)
- Spring学习之AOP基础
- 使一个布局中的所有事件失效
- DC-4: 循环结构
- CSS基础知识一
- POJ 3159 Candies 笔记