Java多线程:线程间通信之volatile与sychronized这篇文章中我们了解了synchronized的基本特性,知道了一旦有一个线程访问某个对象的synchronized修饰的方法或代码区域时,该线程则获取这个对象的锁,其他线程不能再调用该对象被synchronized影响的任何方法。那么,如果这个线程自己调用该对象的其他synchronized方法,Java是如何判定的?这就涉及到了Java中锁的重要特性:可重入性,也就是今天的主题。

1. 线程安全与可重入性

在回答引言的问题前,我们先讲解一下可重入性。在线程这块知识中,可重入性常常和线程安全进行对比。

1.1. 线程安全

线程安全函数的概念比较直观,众所周知,同一进程的不同线程会共享同一主内存,线程的私有栈中只包括PC,栈,操作数栈,局部变量数组和动态链接。对共享内存进行读写时,若要保证线程安全,则必须通过加锁的方式。

1.2. 可重入

1.2.1. 定义

关于可重入这一概念,我们需要参考维基百科。

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

1.2.2. 可重入的条件

  • 不在函数内使用静态或全局数据。
  • 不返回静态或全局数据,所有数据都由函数的调用者提供。
  • 使用本地数据(工作内存),或者通过制作全局数据的本地拷贝来保护全局数据。
  • 不调用不可重入函数。

1.3. 可重入与线程安全

一般而言,可重入的函数一定是线程安全的,反之则不一定成立。在不加锁的前提下,如果一个函数用到了全局或静态变量,那么它不是线程安全的,也不是可重入的。如果我们加以改进,对全局变量的访问加锁,此时它是线程安全的但不是可重入的,因为通常的枷锁方式是针对不同线程的访问(如Java的synchronized),当同一个线程多次访问就会出现问题。只有当函数满足可重入的四条条件时,才是可重入的。

2. synchronized的可重入性

2.1. synchronized是可重入锁

回到引言里的问题,如果一个获取锁的线程调用其它的synchronized修饰的方法,会发生什么?

从设计上讲,当一个线程请求一个由其他线程持有的对象锁时,该线程会阻塞。当线程请求自己持有的对象锁时,如果该线程是重入锁,请求就会成功,否则阻塞。

我们回来看synchronized,synchronized拥有强制原子性的内部锁机制,是一个可重入锁。因此,在一个线程使用synchronized方法时调用该对象另一个synchronized方法,即一个线程得到一个对象锁后再次请求该对象锁,是永远可以拿到锁的

在Java内部,同一个线程调用自己类中其他synchronized方法/块时不会阻碍该线程的执行,同一个线程对同一个对象锁是可重入的,同一个线程可以获取同一把锁多次,也就是可以多次重入。原因是Java中线程获得对象锁的操作是以线程为单位的,而不是以调用为单位的。

2.2. synchronized可重入锁的实现

之前谈到过,每个锁关联一个线程持有者和一个计数器。当计数器为0时表示该锁没有被任何线程持有,那么任何线程都都可能获得该锁而调用相应方法。当一个线程请求成功后,JVM会记下持有锁的线程,并将计数器计为1。此时其他线程请求该锁,则必须等待。而该持有锁的线程如果再次请求这个锁,就可以再次拿到这个锁,同时计数器会递增。当线程退出一个synchronized方法/块时,计数器会递减,如果计数器为0则释放该锁。

3. 参考文章

可重入函数与线程安全函数

可重入

java内置锁synchronized的可重入性

Java多线程:synchronized的可重入性的更多相关文章

  1. Synchronized之四:Synchronized的可重入性

    本文里面讲的是广义上的可重入锁,而不是单指JAVA下的ReentrantLock. 可重入锁,也叫做递归锁,指的是同一线程外层函数获得锁之后 ,内层递归函数仍然有获取该锁的代码,但不受影响.在JAVA ...

  2. Java内置锁synchronized的可重入性

    学习自 https://blog.csdn.net/aigoogle/article/details/29893667 对我很有帮助 感谢作者

  3. JAVA锁的可重入性

    机制:每个锁都关联一个请求计数器和一个占有他的线程,当请求计数器为0时,这个锁可以被认为是unhled的,当一个线程请求一个unheld的锁时,JVM记录锁的拥有者,并把锁的请求计数加1,如果同一个线 ...

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

    什么是可重入锁? 关于什么是可重入锁,我们先来看一段维基百科的定义. 若一个程序或子程序可以“在任意时刻被中断然后操作系统调度执行另外一段代码,这段代码又调用了该子程序不会出错”,则称其为可重入(re ...

  5. java多线程:synchronized和lock比较浅析

    转载:http://www.toutiao.com/a6392135944652587266/?tt_from=weixin&utm_campaign=client_share&app ...

  6. Java锁的深度化--重入锁、读写锁、乐观锁、悲观锁

    Java锁 锁一般来说用作资源控制,限制资源访问,防止在并发环境下造成数据错误 锁作为并发共享数据,保证一致性的工具,在JAVA平台有多种实现(如 synchronized(重量级) 和 Reentr ...

  7. 并发编程系列之Lock锁可重入性与公平性

    一.相似之处:Lock锁 vs Synchronized 代码块 Lock锁是一种类似于synchronized 同步代码块的线程同步机制.从Java 5开始java.util.concurrent. ...

  8. Labview-vi的可重入性

    VI可重入性: labview多线程中 同时对一个子vi访问时,可能会造成同时对同一块内存地址读写所造成的数据混乱,当选择 vi属性(Ctrl+i)中执行选项卡允许可重入时,labview会分配不同的 ...

  9. Java多线程之ReentrantLock重入锁简介与使用教程

    转载请注明原文地址:http://www.cnblogs.com/ygj0930/p/6543947.html  我们知道,线程安全问题需要通过线程之间的同步来解决,而同步大多使用syncrhoize ...

随机推荐

  1. 【Android 应用开发】 ActionBar 基础

    作者 : 万境绝尘 (octopus_truth@163.com) 转载请注明出处 : http://blog.csdn.net/shulianghan/article/details/3920439 ...

  2. OJ题:字符串最后一个单词的长度

    题目描述 计算字符串最后一个单词的长度,单词以空格隔开. 输入描述: 一行字符串,非空,长度小于5000. 输出描述: 整数N,最后一个单词的长度. 输入例子: hello world 输出例子: 5 ...

  3. Android重命名包名

    工程写的差不多了才发现原来用的包名还是自己尝试性的进行写代码的时候用到的.但apk的发布,google map api的申请等等方面都需要用到一个比较规范的包名.这就涉及到修改包名的问题. 包名一开始 ...

  4. HashMap与HashTable面试宝典

    u012233832的专栏 初生牛犊 目录视图 摘要视图 订阅 写博客,送money.送书.送C币啦   7-8月博乐推荐文章    砸BUG 得大奖 100%中奖率   微信开发学习路线高级篇上线  ...

  5. Android ViewManger解析 从ViewRoot 源码分析invalidate

    转载请标明出处:http://blog.csdn.net/sk719887916/article/details/48443429,作者:skay     通过学习了AndroidUI之绘图机基础知道 ...

  6. PorterDuffXferMode不正确的真正原因PorterDuffXferMode深入试验)

    菜鸡wing遇敌PorterDuffXferMode,不料过于轻敌,应战吃力.随后与其大战三天三夜,三百余回合不分胜负.幸得 @咪咪控 相助,侥幸获胜. 关键字:PorterDuffXferMode ...

  7. 软考论文的六大应对策略V1.0

    软考论文的六大应对策略V1.0 短短2个小时,要写3000字的文章,对习惯了用电脑敲字.办公的IT从业人员而言,难度不小.尤其,大家会提笔忘字.笔者的应试策略,就是勤学苦练,考试前的一个星期,摸清套路 ...

  8. Debian系列软件管理(第二版)

    Debian系列软件管理 1.搜索软件包信息 apt-cache search apt-cache search yum 2.查看软件包信息 apt-cache show rpm 3.安装软件 apt ...

  9. RedHat系列软件管理(第二版) --脚本安装

    RedHat系列软件管理 --脚本安装 一.解压缩 tar -zxvf webmin-1.700.tar.gz 二.进入相关目录 cd webmin-1.700 三.如果此时执行./configure ...

  10. Spring--ApplicationContext

    //中心接口,给应用提供配置信息 public interface ApplicationContext extends EnvironmentCapable, ListableBeanFactory ...