死锁
线程同步操作的是同一个线程对象,所以可能造成线程不安全,出现非数据的原子操作,所以,需要加锁,同时线程是程序的执行顺序,也就是cpu根据不同时间片选择某个时间执行某个线程,关于线程并发,在以前的总结中做过了几个简单的总结。
而死锁最经典的例子就是哲学家进餐问题,每个哲学家都左手拿着一只筷子,并且总共有五个哲学家,5个筷子,只有当哲学家左右手都有筷子时才能进餐,所以每个哲学家都在等右边哲学家方上筷子,处于僵持等待状态,称为死锁。
这里模仿两个线程死锁的情况
结果:
flag=1
flag=0
大概分析一下,该类本身是一个线程类,flag用来控制执行哪个锁,O1和O2是两个被锁住对象,flag为1时先锁住o1,在锁住o2,flag为0则相反,而死锁发生就在此处两个线程启动了,o1被锁住了,另一个o2被锁住了,都在等待对方释放锁,显然处于僵持,产生死锁,
解决死锁的一个简单办法就是增大锁的粒度,扩大锁对象,比如讲前面的O1与O2改成this
结果:
flag=1
flag=0
1
0
生产者与消费者
概述,模拟一个生产者利用生产食物放到篮子里,而一个消费者从篮子里消费食物
消费利用一对生产者和消费者模拟
UtilStack ss=new UtilStack(); Producer p=new Producer(ss); Consumer c=new Consumer(ss); new Thread(p).start(); new Thread(c).start();
结果如下:
生产了0
消费了0
生产了1
生产了2
消费了2
生产了3
生产了4
消费了4
生产了5
生产了6
消费了6
生产了7
full
消费了7
生产了8
full
消费了8
生产了9
full
消费了9
生产了10
full
消费了10
生产了11
full
消费了11
生产了12
full
消费了12
生产了13
full
消费了13
生产了14
full
消费了14
生产了15
full
这里优于设置了消费者消费时间长,所以导致index不一样。可以发现当生产者满了,生产者不生产了,进入休息区,等待被唤醒,关于wait()、notify()、notifyAll(),在之前的多线程总结中已总结了
结果分析
从中我们可以看到生产者有满了的情况,但是消费者消费完了,index就不满了,然后就去叫醒了生产者继续生产,同样如果我们把消费者时间设置短一点看看,预测应该是empty的,在被生产者叫醒
生产了0
消费了0
empty
消费了1
生产了1
empty
消费了2
生产了2
empty
消费了3
生产了3
empty
生产了4
消费了4
empty
最后不得不说生产者与消费者问题可以解决平时在项目开发配置中不求甚解的一些问题,像缓冲区、连接池、消息队列、死锁、同步等等,