我们在多线程编程中,经常会遇到线程同步的问题,我们常常会选择给共享资源上锁来保持线程资源的一致性,这就会导致有可能出现死锁的可能性。
package lock;
//测试死锁
public class TestLock {
public static void main(String[] args) {
Thread father = new Person("爸爸",1);
Thread son = new Person("儿子",2);
father.start();
son.start();
System.out.println("全部获取到交通工具");
}
}
//单车
class Bike{
}
//汽车
class Car{
}
//人
class Person extends Thread{
//内置自行车对象
private static Bike bike = new Bike();
//内置汽车对象
private static Car car = new Car();
//选择类型
private int choice;
//名字
private String personName;
public Person(String personName, int choice) {
this.choice = choice;
this.personName = personName;
}
@Override
public void run(){
try {
getTransport();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//获取交通工具
public void getTransport() throws InterruptedException {
//当选择1时 先骑车在开车
if(choice==1){
Thread.sleep(200);
synchronized (bike){
System.out.println(personName+":要骑自行车啦");
synchronized (car){
System.out.println(personName+":骑完自行车要开汽车啦");
}
}
}else{
Thread.sleep(200);
//当选择不等于1时 先开车 在骑车
synchronized (car){
System.out.println(personName+":要开汽车啦");
synchronized (bike){
System.out.println(personName+":开完汽车要骑自行车啦");
}
}
}
}
}
我们看一下上面的代码,家里有一辆自行车和一辆汽车,交通工具一个时间只能够一个人使用,
我们在getTransport()
里面设置了choice为1
就先骑车再开车,否则就先开车在骑车。我们看下结果。
全部获取到交通工具
儿子:要开汽车啦
爸爸:要骑自行车啦
程序并没有直接结束,而陷入了无限等待状态,这就是死锁。因为爸爸和儿子同时获取交通工具,并同时获取到了锁,两个人都在等待对方的锁释放,而陷入了一种互相等待状态。
我们修改getTransport()方法:
//获取交通工具
public void getTransport() throws InterruptedException {
//当选择1时 先骑车在开车
if(choice==1){
Thread.sleep(2000);
synchronized (bike){
System.out.println(personName+":要骑自行车啦");
}
synchronized (car){
System.out.println(personName+":骑完自行车要开汽车啦");
}
}else{
Thread.sleep(2000);
//当选择不等于1时 先开车 在骑车
synchronized (car){
System.out.println(personName+":要开汽车啦");
}
synchronized (bike){
System.out.println(personName+":开完汽车要骑自行车啦");
}
}
}
再试一次:
儿子:要开汽车啦
爸爸:要骑自行车啦
爸爸:骑完自行车要开汽车啦
儿子:开完汽车要骑自行车啦
全部获取到交通工具
发现死锁消失了,爸爸和儿子都获取到了交通工具。
总结:
产生死锁的四个必要条件:
- 互斥条件:一个资源一次只能被一个线程使用。
- 请求与保持条件:一个线程请求资源而阻塞时,对已获得资源保持不放。
- 不剥夺条件:线程已获得资源,在未使用完之前不能强行剥夺。
- 循环等待条件:若干线程形成一种头尾相接的循环等待资源关系。
若要避免死锁,只要打破上述四个条件中的一个即可。