ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

synchronized 是可重入锁吗?为什么?

2021-03-24 23:06:04  阅读:159  来源: 互联网

标签:重入 为什么 请求 synchronized ReentrantLock 该锁 线程


最近有人私信我,说面试中问到了 synchronized,被批的一塌糊涂,挂了!Why?他说其中一个问题,问他 synchronized 是可重入锁吗?他说不是!为什么不是,他说 java 中有 ReentrantLock,ReentrantLock 是可重入锁,所以 synchronized 就不是。因为 synchronized 是可重入锁的话,ReentrantLock 就没有存在的必要!

当他说完这句话,我就知道他没理解 synchronized,也没理解 ReentrantLock。那没关系,昨天不理解,今天理解了就是一种进步!希望通过本文,我们能加深对 synchronized 的认识。

关于 ReentrantLock 我准备放在以后再说!好吧,我们先来看看可重入锁的定义!

什么是可重入锁?
关于什么是可重入锁,我们先来看一段维基百科的定义。

若一个程序或子程序可以“在任意时刻被中断然后操作系统调度执行另外一段代码,这段代码又调用了该子程序不会出错”,则称其为可重入(reentrant或re-entrant)的。即当该子程序正在运行时,执行线程可以再次进入并执行它,仍然获得符合设计时预期的结果。与多线程并发执行的线程安全不同,可重入强调对单个线程执行时重新进入同一个子程序仍然是安全的。

通俗来说:当线程请求一个由其它线程持有的对象锁时,该线程会阻塞,而当线程请求由自己持有的对象锁时,如果该锁是重入锁,请求就会成功,否则阻塞。

synchronized 是可重入锁吗?
我先给大家一个结论:synchronized 是可重入锁!

假设我们现在不知道它是不是一个可重入锁,那我们就应该想方设法来验证它是不是可重入锁?怎么验证呢?看下面的代码!

synchronized 是可重入锁吗?为什么?

上面的代码也不是随便写的,我是根据维基百科的定义写出这段代码来验证它。现在运行一下上面的代码,我们看一下结果:

synchronized 是可重入锁吗?为什么?

现在可以验证出 synchronized 是可重入锁了吧!因为这些方法输出了相同的线程名称,表明即使递归使用synchronized也没有发生死锁,证明其是可重入的。

还看不懂?那我就再解释下!

这里的对象锁只有一个,就是 child 对象的锁,当执行 child.doSomething 时,该线程获得 child 对象的锁,在 doSomething 方法内执行 doAnotherThing 时再次请求child对象的锁,因为synchronized 是重入锁,所以可以得到该锁,继续在 doAnotherThing 里执行父类的 doSomething 方法时第三次请求 child 对象的锁,同样可得到。如果不是重入锁的话,那这后面这两次请求锁将会被一直阻塞,从而导致死锁。

所以在 java 内部,同一线程在调用自己类中其他 synchronized 方法/块或调用父类的 synchronized 方法/块都不会阻碍该线程的执行。就是说同一线程对同一个对象锁是可重入的,而且同一个线程可以获取同一把锁多次,也就是可以多次重入。因为java线程是基于“每线程(per-thread)”,而不是基于“每调用(per-invocation)”的(java中线程获得对象锁的操作是以线程为粒度的,per-invocation 互斥体获得对象锁的操作是以每调用作为粒度的)。

可重入锁的实现原理?
看到这里,你终于明白了 synchronized 是一个可重入锁。但是面试官要再问你,可重入锁的原理是什么?

对不起,你又卡壳了。

那么我现在先给你说一下,可重入锁的原理。具体我们后面再写 ReentrantLock 的时候来验证或看它源码。

重入锁实现可重入性原理或机制是:每一个锁关联一个线程持有者和计数器,当计数器为 0 时表示该锁没有被任何线程持有,那么任何线程都可能获得该锁而调用相应的方法;当某一线程请求成功后,JVM会记下锁的持有线程,并且将计数器置为 1;此时其它线程请求该锁,则必须等待;而该持有锁的线程如果再次请求这个锁,就可以再次拿到这个锁,同时计数器会递增;当线程退出同步代码块时,计数器会递减,如果计数器为 0,则释放该锁。

好了,由于时间关系,我们下次再见!

synchronized 是可重入锁吗?为什么?

最后,欢迎关注我的个人微信公众号:业余草(yyucao)!可加QQ1群:135430763(2000人群已满),QQ2群:454796847,QQ3群:187424846。QQ群进群密码:xttblog,想加微信群的朋友,可以微信搜索:xmtxtt,备注:“xttblog”,添加助理微信拉你进群。备注错误不会同意好友申请。再次感谢您的关注!后续有精彩内容会第一时间发给您!原创文章投稿请发送至532009913@qq.com邮箱。商务合作可添加助理微信进行沟通!

转发也是一种力量!

标签:重入,为什么,请求,synchronized,ReentrantLock,该锁,线程
来源: https://blog.51cto.com/15127565/2671232

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有