synchronized是可重入锁吗,及其实现原理?

先说答案吧!
synchronized是可重入锁。
简单点说,可重入锁是:同一个线程重复请求由自己持有的锁对象时,可以请求成功而不会发生死锁。
在网上看见一个例子,感觉不错。我自己试了一下,可以证明synchronized是可重入锁

子类

package cn.org.test;

/**
 * *************************************************************************
 * 

* * @文件名称: ChildProgram.java * @包 路 径: cn.org.test * @版权所有:北京数字认证股份有限公司 (C) 2019 * @类描述: * @版本: V1.0 @创建人:wangyangyang * @创建时间:2019-8-24 18:03 */ public class ChildProgram extends SuperProgram { public static void main(String[] args) { ChildProgram childProgram = new ChildProgram(); childProgram.childSomeSthing(); } public synchronized void childSomeSthing (){ superDoSomeSthing(); System.out.println("child do Something"); } @Override public synchronized void superDoSomeSthing() { System.out.println("child do Something"); super.superDoSomeSthing(); } } 父类 package cn.org.test; /** * ************************************************************************* *

* * @文件名称: SuperProgram.java * @包 路 径: cn.org.test * @版权所有:北京数字认证股份有限公司 (C) 2019 * @类描述: * @版本: V1.0 @创建人:wangyangyang * @创建时间:2019-8-24 18:03 */ public class SuperProgram { public synchronized void superDoSomeSthing (){ System.out.println("super,doing something"); } }

执行结果:

child do Something
super,doing something
child do Something

Process finished with exit code 0

可以看到调用的三个方法均得到了执行。我们知道synchronized修饰普通方法时,使用的是对象锁,也就是ChildProgram对象。三个方法的锁都是ChildProgram对象。我们在子类中执行childSomeSthing方法时,获取了ChildProgram对象锁,然后在childSomeString时调用了重写父类的superDoSomeSthing方法,该方法的锁也是ChildProgram对象锁,然后在其中调用父类的superDoSomeSthing方法,该方法的锁也是ChildProgram对象锁。一个锁多次请求,而且都成功了,所以synchronized是可重入锁。

synchronized可重入锁的实现原理:
synchronized底层的实现原理是利用计算机系统的mutex Lock实现。每一个可重入锁都会关联一个线程ID和一个锁状态status。
当一个线程请求方法时,会去检查锁状态,如果锁状态是0,代表该锁没有被占用,直接进行CAS操作获取锁,将线程ID替换成自己的线程ID。如果锁状态不是0,代表有线程在访问该方法。此时,如果线程ID是自己的线程ID,如果是可重入锁,会将status自增1,然后获取到该锁,进而执行相应的方法。如果是非重入锁,就会进入阻塞队列等待。
释放锁时,可重入锁,每一次退出方法,就会将status减1,直至status的值为0,最后释放该锁。
释放锁时,非可重入锁,线程退出方法,直接就会释放该锁。

所以,从一定程度上来说,可重入锁可以避免死锁的发生。

你可能感兴趣的:(多线程,Thread)