乐趣区

关于java:我所知道并发编程之理解死锁与重入锁

前言


咱们来理解几个锁的概念,就是自旋锁、死锁、重入锁

一、重入锁


首先来看重入锁,也就是锁重入,什么意思呢?先说非重入锁

咱们晓得当多个线程来拜访一个曾经加了一个 synchronized 的办法的时候一个线程拿到咱们的锁之后,那么,其余的线程就须要期待

当第一个线程执行结束开释了这个锁之后,那么其余的线程才可能再进来

那么这就是说锁是不可能让所有的线程都进来的,只能有一个线程进来,而后其余的线程都在里面等着

那么锁重入是什么意思呢?比如说同一个实例中有两个办法都应用 synchronized

那么第一个线程在第一个办法中获取了 synchronized 的锁,而在第一个办法里会去调用第二个办法,这时也是也能够的

咱们才用代码模仿一下单线程下的这种个状况

class Demo1{public synchronized void a(){System.out.println("输入 a");
        b();}

    public synchronized void b(){System.out.println("输入 b");
    }
}
public static void main(String[] args) {new Thread(new Runnable() {
        @Override
        public void run() {Demo1 demo1 = new Demo1();
            demo1.a();}
    }).start();}
// 运行后果如下:输入 a
输入 b 

而多线程的时候,是什么状况呢?应用代码来看看

public static void main(String[] args) {Demo1 demo1 = new Demo1();

        new Thread(new Runnable() {
            @Override
            public void run() {System.out.println(Thread.currentThread()+"执行办法");
                demo1.b();}
        }).start();

        new Thread(new Runnable() {
            @Override
            public void run() {System.out.println(Thread.currentThread()+"执行办法");
                demo1.a();}
        }).start();}
// 运行后果如下:Thread[Thread-0,5,main] 执行办法
输入 b

Thread[Thread-1,5,main] 执行办法
输入 a
输入 b 

二、死锁


死锁之前有说过哲学家吃饭的问题,这里采纳代码实际了解一下

当一个线程永远的持有一把锁,并且其余线程都尝试取得这把锁的时候,那么就产生了死锁

咱们先创立两把锁看看怎么样

class Demo2{private Object object1 = new Object();

    private Object object2 = new Object();


    private  void a(){synchronized (object1){
        try {Thread.sleep(1000);
            } catch (InterruptedException e) {e.printStackTrace();
            }
            synchronized (object2){System.out.println("hi");
            }
        }
    }

    private  void b(){synchronized (object2){synchronized (object1){System.out.println("hi");
            }
        }
    }
}

接下来咱们创立两个线程别离执行 a 与 b 办法看看

public static void main(String[] args) {Demo2 demo2 =new Demo2();
    new Thread(new Runnable() {
        @Override
        public void run() {demo2.a();
        }
    }).start();

    new Thread(new Runnable() {
        @Override
        public void run() {demo2.b();
        }
    }).start();}

// 运行后果如下:

程序卡在这里了产生了死锁,线程一执行 a() 办法拿到了 obj1 锁,线程二执行 b() 办法拿到了 obj2 锁

当初线程一没有开释 obj1 锁,于是第二个线程来申请 obj1 锁,那么就要期待

当初线程二在期待着,obj2 锁必定没有开释于是线程一又来申请 obj2 锁,所以线程一也处于期待状态

咱们能够应用 jconsole 检测死锁,关上查看刚刚的死锁检测

参考资料


龙果学院:并发编程原理与实战(叶子猿老师)

退出移动版