-->

最简单的模拟真实多线程死锁的场景,适合刚学习多线程的新手看

2020-08-15 05:14发布

首先介绍下什么是死锁

个人理解:死锁指的是在多线程中(至少存在2个线程),线程之间持有各自所需要的锁,互相等待对方释放锁资源,形成无限等待的情况,这种场景叫做死锁

 

上面那句话可能不是很好理解,我举一个例子:

有两个人,一个叫小明,一个叫小红,他们关系特别好,吃饭共用一套碗筷      

到饭点了,小明和小红一起去吃饭,小明先拿到了碗,正准备拿筷子的时候,却被小红抢先一步,

小明说:你把筷子给我,我要先去吃饭,吃完给你,小红不肯,说:你先把碗给我,我吃完了再给你

这样两个人,你不让我,我不让你,互怼,形成一种僵持的局面,

最后两个人都没吃到饭,然后 ‘卒’,享年9岁

 

上面的 例子中,小明和小红代表了程序中的两个线程,而碗和筷子代表了锁资源,而吃饭的动作相当于后续要执行的业务逻辑,只有同时拥有了碗和筷子才能 吃饭。

相信看完上面例子,你对死锁应该会有一个比较初步清晰的认识

 

那么什么情况下为什么会产生死锁呢?

出现死锁,一般发生在同步方法嵌套的场景中,像下面这样子

    private void test() {
      
        synchronized (obj1) {
           XXXXX代码
           synchronized (obj2) {
               xxx代码 
           }

        }

    }

或者这样子

同步方法,自带this锁
 private synchronized void test() {
       
        synchronized (obj) {
            xxxxx代码
        }

 }

这里只列了2层锁嵌套,可能还有3层,4层,5层。。。。为了简单,好理解就不列了那么多了

说了那么多,那么怎么模拟出死锁呢?

不说太多废话了,直接上代码吧

public class ThreadTest {

    public static void main(String[] args) throws InterruptedException {

        TestThread2 testThread2 = new TestThread2();
        testThread2.setFlag(true);
        Thread thread1 = new Thread(testThread2,"线程A");
        Thread thread2 = new Thread(testThread2,"线程B");
        thread1.start();
        Thread.sleep(10);//这里休眠的目的是让线程A先执行,保证A线程进入if里面,B线程进入else里面
        testThread2.setFlag(false);
        thread2.start();
    }

}

 

public class TestThread2 implements Runnable {

    private int count=100000;

    private Object obj=new Object();

    private boolean flag;

    public boolean isFlag() {
        return flag;
    }

    public void setFlag(boolean flag) {
        this.flag = flag;
    }

    @Override
    public  void run() {

        if (flag) {
            synchronized (obj) {
                try {
                    System.out.println(Thread.currentThread().getName()+"拿到了obj锁");
                    Thread.sleep(40);//这里休眠是让B线程有机会拿到this锁
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                decrCount();
            }
        }else{
            decrCount();
        }
    }

    //同步方法默认使用this锁
    private synchronized void decrCount() {
        System.out.println(Thread.currentThread().getName()+"拿到了this锁");
        //这里一定要加上obj锁才能成功模拟出死锁的场景
        synchronized (obj) {
            while (count >0){
                System.out.println(Thread.currentThread().getName()+":"+count);
                count--;
            }
        }

    }
}

 

有啥不懂的,可以加群798733709一起交流学习,群里很多都是工作4-5年的大牛。

写文章是在是太难了 ,如果有帮到你,点个赞再走呗

    

 

标签: