简单易懂的多线程死锁问题

70 阅读1分钟

死锁概念

多个线程因竞争同一个资源,而造成的相互等待的状态,如果不加干预,将会一直持续下去,这就是死锁。

例子:嵌套同步代码

public class Test {
    public Object mLock1 = new Object();
    public Object mLock2 = new Object();
    public void test1() {
        synchronized (mLock1) {
            //do something
            synchronized (mLock2) {
                //do something
            }
        }
    }

    public void test2() {
        synchronized (mLock2) {
            //do something
            synchronized (mLock1) {
                //do something
            }
        }
    }
}

具体例子:能运行的,通俗易懂的

package interview.learnjava21;

import java.util.concurrent.TimeUnit;


public class Test {

    public static void main(String[] args) {
        MarkUp markUp0 = new MarkUp("迪丽热巴",0);
        MarkUp markUp1 = new MarkUp("杨幂",1);
        markUp0.start();
        markUp1.start();
    }
}

// 口红类
class LipStick {
}

// 镜子类
class Mirror {
}

// 化妆类
class MarkUp extends Thread {

    private int choice;
    private String userName;

    private static LipStick lipStick = new LipStick();
    private static Mirror mirror = new Mirror();

    MarkUp(String userName, int choice) {
        this.userName = userName;
        this.choice = choice;
    }

    @Override
    public void run() {
        try {
            markUP();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    private void markUP() throws InterruptedException {
        // 如果选择0方式化妆
        if (choice == 0) {
            // 同步代码块的锁,在同步代码块有效
            synchronized (lipStick) {
                System.out.println(userName + "拿到了口红");
                // 拿到口红后再拿镜子
                TimeUnit.SECONDS.sleep(1);
                // 程序执行此处会停止       -----------------这里死锁----------------------->
                synchronized (mirror) {
                    System.out.println(userName + "拿到了镜子");
                }
            }
        }
        // 如果选择1方式化妆
        if (choice == 1) {
            // 同步代码块的锁,在同步代码块有效
            synchronized (mirror) {
                System.out.println(userName + "拿到了镜子");
                // 拿到镜子后再拿口红
                TimeUnit.SECONDS.sleep(1);
                // 程序执行此处会停止     -----------------这里死锁----------------------->
                synchronized (lipStick) {
                    System.out.println(userName + "拿到了口红");
                }
            }
        }
    }
}

如果不让他形成死锁,就需要修改同步代码块,不能让同补代码块嵌套,这样就可以避免死锁。