死锁
一个线程需要同时获得多把锁,这时就容易发生死锁
t1 线程 获得A对象锁,接下来想获取B对象的锁
t2 线程 获得B对象锁,接下来想获取A对象的锁
首先 t1 线程获得A对象锁,t2线程获得B对象锁,0.5秒后,t2尝试获得A对象的锁,陷入阻塞状态,再过0.5秒之后,t1 线程尝试获得B对象锁,也陷入了阻塞,发生了死锁
哲学家就餐问题
有五位哲学家,围坐在圆桌旁
- 他们只做两件事,思考和吃饭,思考一会儿吃口饭,吃完饭接着思考
- 吃饭时要用两根筷子吃,桌上共有五根筷子,每位哲学家左右手各有一根筷子
- 如果筷子被身边的人拿着,自己就得等待
假设一种场景,五个人每个人都拿了一根筷子,但是因为要两根筷子才可以吃饭,因此五个人就都等待着其他人释放资源,造成了死锁。
筷子类
哲学家类
测试类
某个情况下就会出现,一个人只拿了一个筷子 ,相互造成了死锁
活锁
可以通过增加一些随机的睡眠时间来避免活锁的产生
饥饿
一个线程由于优先度太低,始终得不到CPU的调度执行,也不能结束。
上图是一个死锁的情况,t1线程先获取的对象锁A,t2线程先获取的对象锁B,然后都尝试获取对方的锁对象,造成了死锁。
但如果设置加锁的顺序,比如都按照先对A加锁,再对B加锁的顺序,如图
线程1,2同时尝试获取对象A锁,线程1获取到了,线程2陷入阻塞,这样就避免了死锁的产生
在看哲学家问题
阿基米德没有按照顺序获取锁,就可能会造成死锁,当我们把顺序改为,先获取c1,再获取c5的时候
在运行程序,我们就会发现不会产生死锁的问题
但是观察运行结果发现,有一些线程永远都不会被执行,这就发生了饥饿现象。