前言
咱们来理解几个锁的概念,就是自旋锁、死锁、重入锁
一、重入锁
首先来看重入锁,也就是锁重入,什么意思呢?先说非重入锁
咱们晓得当多个线程来拜访一个曾经加了一个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]执行办法输入bThread[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检测死锁,关上查看刚刚的死锁检测
参考资料
龙果学院:并发编程原理与实战(叶子猿老师)