死锁
1.有一个线程,针对同一把锁,连续加锁两次,如果产生了锁死,就是不可重入锁
public static synchronized void increase()//锁加锁加到静态方法上就是对类对象加锁,其他的都是加载到this上
{
synchronized(this)
{
}
}
上述代码1.调用方法,先针对this加锁,此时假设加锁成功了2.接下来往下执行,代码块中也加了一个锁,此时针对方法的锁还没有释放,代码块中的就不会得到,此时就会产生锁竞争。如果是一个不可重入锁,这把锁不会保存,是哪一个线程对他加锁,只要它当前处于加锁状态,收到了“加锁”的请求,就会当即拒绝这个请求,而不管当下是那个线程,都会产生死锁,而可重入锁,则会让这个所保存起来,是哪个线程加上锁,后续收到加锁请求就会先对比一下,看看枷锁线程是不是当前持有这把锁,这个时候就可以了灵活判断了(synchronized本身是一个可重入锁),若加锁很多个,那就是在最外面的那个锁解开,(增加一个计数器,遇到加锁+1,解锁-1,在零处释放)。
2.两个线程,两把锁,这两个线程分别获取到一把锁,然后尝试获取对方的锁。
public class dome1 {
public static Object locker1=new Object();
public static Object locker2=new Object();
public static void main(String[] args) {
Thread t1=new Thread(()->{
synchronized (locker1)
{
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (locker2) {
System.out.println("t1");
}
}
});
Thread t2=new Thread(()->{
synchronized (locker2)
{
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (locker1) {
System.out.println("t2");
}
}
});
t1.start();
t2.start();
}
}
3.N个线程M个锁
典型问题:哲学家吃面问题
问:1.哲学家思考人生的时候会放下筷子2.吃面时,会拿起左手和右手的筷子,再去加面条吃
条件:1.每个哲学家,啥时候思考人生,啥时候吃面条是不确定的;2.每个哲学家都很固执,如果他的筷子每人使用了,他就会出发阻塞,等到别人放下筷子
当五个哲学家都想吃面,就会出现死锁。
如何避免死锁
1.先要明确死锁的必要条件:
1)互斥使用,一个线程获得一个锁后,别的线程就不能获得。
2)不可抢占:锁只有是被持有者释放才能有别的线程会得到锁
3)请求和保持:这一个线程去尝试获取多把锁,在获取第二把锁的时候,会保持对第一把所得获取状态;
4)循环等待:t1尝试获取locker2,需要先执行完t2,t2尝试获取locker1,需要先执行完t1;
2.可以发现四个条件时同时满足才可发生死锁,所以只要破坏一个即可打破死锁。最有可能打破四
3.解决办法
1)银行家算法-》较为麻烦
2)针对锁编号,规定加锁的顺序严格遵守,比如规定,每个线程如果要获取多把锁,就必须先获取编号小的锁,后获取编号打的锁,