博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
synchronized的可重入性
阅读量:4965 次
发布时间:2019-06-12

本文共 1251 字,大约阅读时间需要 4 分钟。

今天看并发编程实战,看到一个实例

public class Widget {  

    public synchronized void doSomething() {  
        ...  
    }  
}  
  
public class LoggingWidget extends Widget {  
    public synchronized void doSomething() {  
        System.out.println(toString() + ": calling doSomething");  
        super.doSomething();  
    }  
}  

原本以为是说会发生死锁。可是自己执行了之后,发现没有死锁。然后找到了合理的解释,实际上对象锁是同一个,即子类对象的锁,而对象锁具有可重入性,确保不会发生死锁。

以下内容转载 大神“Mat的学习过程”的博客 http://blog.csdn.net/aigoogle/article/details/29893667?utm_source=tuicool&utm_medium=referral

----------------------------------------------------------------------

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

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

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

转载于:https://www.cnblogs.com/govoid/p/5396348.html

你可能感兴趣的文章
Gitlab配置、备份、升级、迁移
查看>>
dataTable.NET的search box每輸入一個字母進行一次檢索的問題
查看>>
Python 文件处理
查看>>
邻接表详解
查看>>
android,radio,checkbox
查看>>
Steven-Java-变量
查看>>
Spring MVC 的概念1
查看>>
JAVA 上传图片功能
查看>>
编程中i++与++i的区别
查看>>
[8.2] Robot in a Grid
查看>>
Angular4 后台管理系统搭建(9) - 用自定义angular指令,实现在服务端验证
查看>>
ThinkPHP中:RBAC权限控制的实习步骤
查看>>
[转](.NET Core C#) AES Encryption
查看>>
[转]EntityFramework中常用的数据修改方式
查看>>
[转]SQL Collation冲突解决 临时表
查看>>
[转]Gitlab-CI持续集成之Runner配置和CI脚本
查看>>
Spark&Hive结合起来
查看>>
使用Flex和java servlet上传文件
查看>>
软件工程的实践项目课程的自我目标
查看>>
POJ 1321 棋盘问题 (深搜)
查看>>