1.什么是死锁
死锁是多线程代码中常常出现的bug
当想给线程加锁时发现线程的上次的锁还没有及时释放,导致加锁不上
死锁分别有以下几种情况
1.一个线程两把锁:
如果是可重入锁的话是没有问题的,但是如果是不可重入锁的话就会死锁了
synchronized(this){
//synchronized是可重入锁,所以不会死锁
//但是如果是其他锁,放在代码块里,后入的锁需要等到上一个锁释放才能锁上,但是上一个锁的释放又依赖于后入的锁的释放,就好像这个代码块一样,前面的代码块需要必须执行完才能进入第二个代码块,但是前面的代码块执行又依赖于第二个代码块的执行
synchronized(this){}
}
2.两个线程两把锁
线程1获取到了锁A
线程2获取到了锁B
如果线程1尝试获取锁B或者线程2尝试获取锁A,这时候就会死锁
就好比,小孩子打架,小明拿着娃娃想要换小红的超人,两者都说你给我我就给你,结果两个都不肯,这是后就一直僵持不下了.
3.N个线程M把锁:
这时候引出一个情景:哲学家就餐问题:(概率问题)
总结一下形成死锁的四个必要条件:(锁的基本特点)
1.互斥使用,1线程拿到A锁,其他线程就不能获取A锁
2.不可抢占:1线程拿到A锁,其他线程就只能阻塞等待锁A在1线程中释放,不能强行把他抢占
3.请求和保持:1线程拿到A锁后,就会一直持有获取锁这个状态,知道说主动释放.
4.循环等待,1线程等待2线程,2线程又尝试等待1线程.
2.死锁的解决方案
打破等待循环:针对多把锁进行锁编号,并按一定的顺序获取
比如:锁1,2,3,4,5.......约定在获取多把锁的时候要明确获取锁的顺序是从小到大的顺序
线程要拿到1,2两把锁,就先获取1再获取2
要拿到2,4这两把锁,就先获取2,然后再获取4
这种方法就是,对锁编号,并且按顺序加锁,从而打破循环等待