1.死锁是咋回事.
举例说明:程序员A需要修改代码才能展示出正确的二位码,保安B需要正确的二位码才能让A进去修改,A占有的技术(资源)等待B持有的权利(资源)释放,而B占有的权利(资源)等待A的技术(资源)修改,二者僵持不下,如果将A和B看做是线程,则二者都不能执行,若不采取其它措施,这种循环等待状况会无限期持续下去,就发生了进程死锁。
2.死锁的三个典型事例
1.一个线程,一把锁,连续加锁两次.如果锁是不可重入锁,就会死锁.
java里面synchronized和ReentrantLock都是可重入锁
2.两把线程两把锁,t1和t2各自先针对锁A和锁B加锁,在尝试获取对方的锁.
package thread;
public class ThreadDemo13 {
public static void main(String[] args) {
Object chengxuyuan =new Object();
Object baoan =new Object();
Thread t1=new Thread(()->{
synchronized (chengxuyuan){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (baoan){
System.out.println("让我进去,我才能修改一码通");
}
}
});
Thread t2=new Thread(()->{
synchronized (baoan){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (chengxuyuan){
System.out.println("出示一码通才让你进去");
}
}
});
t1.start();
t2.start();
}
}
可以在控制台上看到死锁的具体因素
3.哲学家就餐问题,会产生死锁.
3.可重入和不可重入
可重入:所谓可重入锁,意味着线程可以进入它已经拥有的锁的同步代码块儿.
不可重入:所谓非可重入锁,即若当前线程执行某个方法已经获取了该锁,那么在方法中尝试再次获取锁时,就会获取不到被阻塞,是产生死锁的一种原因.
4.死锁的四个必要条件
1.互斥使用,即当资源被一个线程使用(占有)时,别的线程不能使用。
2.不可抢占,资源请求者不能强制从资源占有者事中夺取资源,资源只能由资源占有者主动释放。
3.请求和保持,即当资源请求者在请求其他的资源的同时保持对原有资源的占有。
4.循环等待,即存在一个等待循环队列:p1 要p2的资源,p2要p1的资源。这样就形成了一个等待环路
只有条件4我们可以用代码来解决
5.如何解决死锁
我们只需要改变线程的环路访问就可以解决
package thread;
public class ThreadDemo13 {
public static void main(String[] args) {
Object chengxuyuan =new Object();
Object baoan =new Object();
Thread t1=new Thread(()->{
synchronized (baoan){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (chengxuyuan){
System.out.println("让我进去,我才能修改一码通");
}
}
});
Thread t2=new Thread(()->{
synchronized (baoan){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (chengxuyuan){
System.out.println("出示一码通才让你进去");
}
}
});
t1.start();
t2.start();
}
}
打印结果