Java——面试题:写出一个死锁的实例(三种情况分析死锁形成原因)

面试题:

写出一个死锁的实例。

 

 

Java发生死锁的根本原因是:

死锁是因为多线程访问共享资源,由于访问的顺序不当所造成的,在申请锁时发生了交叉闭环申请。即线程在获得了锁A并且没有释放的情况下去申请锁B,这时,另一个线程已经获得了锁B,在释放锁B之前又要先获得锁A,因此闭环发生,陷入死锁循环。

 

 

 

实例1:

在MyLock类中定义两个不同的静态锁对象。

package com.deadLock;

class MyLock{
    static Object locka = new Object(); //注意此处必须时static,
    static Object lockb = new Object(); //不仅能类名访问,也是让不同线程访问共享数据
}

class Lock implements Runnable{
    private boolean flag;

    public Lock(boolean flag) {
        this.flag = flag;
    }

    @Override
    public void run() {
        if (flag){
            while(true){
               deadLockab();
            }
        }else{
            while(true){
                deadLockba();
            }
        }
    }

    private void deadLockab() {
        String name = Thread.currentThread().getName();
        synchronized (MyLock.locka){
            System.out.println(name+"...lock on "+MyLock.locka);
            synchronized (MyLock.lockb){
                System.out.println(name+"...lock on "+MyLock.lockb);
            }
        }
    }

    private void deadLockba() {
        String name = Thread.currentThread().getName();
        synchronized (MyLock.lockb){
            System.out.println(name+"...lock on "+MyLock.lockb);
            synchronized (MyLock.locka){
                System.out.println(name+"...lock on "+MyLock.locka);
            }
        }
    }

}

public class DeadLockDemo2 {
    public static void main(String[] args) {
        Thread t1 = new Thread(new Lock(true));
        Thread t2 = new Thread(new Lock(false));
        t1.start();
        t2.start();
    }
}

运行结果(形成死锁):

Java——面试题:写出一个死锁的实例(三种情况分析死锁形成原因)_第1张图片

 

实例2(无法形成死锁):

在实现Runnable类中定义两个不同的锁,注意两个线程任务不同,所以这两个锁并不是默认静态锁。

package com.deadLock;


class Lock implements Runnable{
    private boolean flag;
    private Object obj1 = new Object();
    private Object obj2 = new Object();
    public Lock(boolean flag) {
        this.flag = flag;
    }

    @Override
    public void run() {
        if (flag){
            while(true){
               deadLockab();
            }
        }else{
            while(true){
                deadLockba();
            }
        }
    }

    private void deadLockab() {
        String name = Thread.currentThread().getName();
        synchronized (obj1){
            System.out.println(name+"...lock on "+obj1);
            synchronized (obj2){
                System.out.println(name+"...lock on "+obj2);
            }
        }
    }

    private void deadLockba() {
        String name = Thread.currentThread().getName();
        synchronized (obj2){
            System.out.println(name+"...lock on "+obj2);
            synchronized (obj1){
                System.out.println(name+"...lock on "+obj1);
            }
        }
    }

}

public class DeadLockDemo2 {
    public static void main(String[] args) {
        Thread t1 = new Thread(new Lock(true));
        Thread t2 = new Thread(new Lock(false));
        t1.start();
        t2.start();
    }
}

运行结果:

Java——面试题:写出一个死锁的实例(三种情况分析死锁形成原因)_第2张图片

 

实例3(实例2改进,形成死锁):

在实现Runnable类中定义两个不同的锁,并且两个线程任务不同,两个锁必须手动声明为静态锁。

package com.notdeadlock;


class Lock implements Runnable{
    private boolean flag;
    private static Object obj1 = new Object();
    private static Object obj2 = new Object();
    public Lock(boolean flag) {
        this.flag = flag;
    }

    @Override
    public void run() {
        if (flag){
            while(true){
                deadLockab();
            }
        }else{
            while(true){
                deadLockba();
            }
        }
    }

    private void deadLockab() {
        String name = Thread.currentThread().getName();
        synchronized (obj1){
            System.out.println(name+"...lock on "+obj1);
            synchronized (obj2){
                System.out.println(name+"...lock on "+obj2);
            }
        }
    }

    private void deadLockba() {
        String name = Thread.currentThread().getName();
        synchronized (obj2){
            System.out.println(name+"...lock on "+obj2);
            synchronized (obj1){
                System.out.println(name+"...lock on "+obj1);
            }
        }
    }

}

public class NotDeadLock{
    public static void main(String[] args) {
        Thread t1 = new Thread(new Lock(true));
        Thread t2 = new Thread(new Lock(false));
        t1.start();
        t2.start();
    }
}

 运行结果:

Java——面试题:写出一个死锁的实例(三种情况分析死锁形成原因)_第3张图片

 

实例4(形成死锁(2个线程)):

package com.deadlock3;

class Lock implements Runnable{
    private Object obj1; //注意此处不能为final/static
    private Object obj2;
    //如果final就不能在下面构造方法中重新赋值;如果static所有线程共享锁,线程t1,t2都在使用obj2这把锁,无法形成死锁。

    public Lock(Object obj1, Object obj2) {
        this.obj1 = obj1;
        this.obj2 = obj2;
    }

    @Override
    public void run() {
        while(true){
                deadLock();
        }
    }


    private void deadLock() {
        String name = Thread.currentThread().getName();
        synchronized (obj1){
            System.out.println(name+"...lock on "+obj1);
            synchronized (obj2){
                System.out.println(name+"...lock on "+obj2);
            }
        }
    }
}

public class DeadLockDemo3 {
    public static void main(String[] args) {
        Object obj1 = new Object();
        Object obj2 = new Object();
        Thread t1 = new Thread(new Lock(obj1, obj2));
        Thread t2 = new Thread(new Lock(obj2, obj1));
        t1.start();
        t2.start();
    }
}

运行结果:

Java——面试题:写出一个死锁的实例(三种情况分析死锁形成原因)_第4张图片

 

实例5(形成死锁(3个线程)):

package com.deadlock3;

class Lock implements Runnable{
    private Object obj1; //注意此处不能为final/static
    private Object obj2; 
    //如果final就不能在下面构造方法中重新赋值;如果static所有线程共享锁,最后只有两把锁,无法锁住所有线程。

    public Lock(Object obj1, Object obj2) {
        this.obj1 = obj1;
        this.obj2 = obj2;
    }

    @Override
    public void run() {
        while(true){
                deadLock();
        }
    }


    private void deadLock() {
        String name = Thread.currentThread().getName();
        synchronized (obj1){
            System.out.println(name+"...lock on "+obj1);
            synchronized (obj2){
                System.out.println(name+"...lock on "+obj2);
            }
        }
    }
}

public class DeadLockDemo3 {
    public static void main(String[] args) {
        Object obj1 = new Object();
        Object obj2 = new Object();
        Object obj3 = new Object();
        Thread t1 = new Thread(new Lock(obj1, obj2));
        Thread t2 = new Thread(new Lock(obj2, obj3));
        Thread t3 = new Thread(new Lock(obj3, obj1));
        t1.start();
        t2.start();
        t3.start();
    }
}

 运行结果:

Java——面试题:写出一个死锁的实例(三种情况分析死锁形成原因)_第5张图片

 

 

总结:

推荐使用实例4这种方法形成死锁,代码简单,理解起来也很方便,如果有什么问题,欢迎一起探讨。 

你可能感兴趣的:(2.Java编程)