本文里面讲的是广义上的可重入锁,而不是单指JAVA下的ReentrantLock。

可重入锁,也叫做递归锁,指的是同一线程外层函数获得锁之后 ,内层递归函数仍然有获取该锁的代码,但不受影响。
在JAVA环境下ReentrantLock 和synchronized 都是可重入锁。

一、synchronized的可重入性

  从互斥锁的设计上来说,当一个线程试图操作一个由其他线程持有的对象锁的临界资源时,将会处于阻塞状态,但当一个线程再次请求自己持有对象锁的临界资源时,这种情况属于重入锁,请求将会成功,在java中synchronized是基于原子性的内部锁机制,是可重入的,因此在一个线程调用synchronized方法的同时在其方法体内部调用该对象另一个synchronized方法,也就是说一个线程得到一个对象锁后再次请求该对象锁,是允许的,这就是synchronized的可重入性。
示例1:

package com.dxz.synchronize;

public class AccountingSync implements Runnable {
static AccountingSync instance = new AccountingSync();
static int i = 0;
static int j = 0; @Override
public void run() {
for (int j = 0; j < 1000000; j++) {
// this,当前实例对象锁
synchronized (this) {
i++;
increase();// synchronized的可重入性
}
}
} public synchronized void increase() {
j++;
} public static void main(String[] args) throws InterruptedException {
Thread t1 = new Thread(instance);
Thread t2 = new Thread(instance);
t1.start();
t2.start();
t1.join();
t2.join();

System.out.println("i:"+i);
         System.out.println("j:"+j);

    }
}

结果:

i:2000000
j:2000000

正如代码所演示的,在获取当前实例对象锁后进入synchronized代码块执行同步代码,并在代码块中调用了当前实例对象的另外一个synchronized方法,再次请求当前实例锁时,将被允许,进而执行方法体代码,这就是重入锁最直接的体现,需要特别注意另外一种情况,当子类继承父类时,子类也是可以通过可重入锁调用父类的同步方法。注意由于synchronized是基于monitor实现的,因此每次重入,monitor中的计数器仍会加1。

示例2:继承类环境下的可重入性

package com.dxz.synchronize;

public class AccountingSyncImpl extends AccountingSync {
static AccountingSync instanceImpl = new AccountingSyncImpl();
public synchronized void reduce() {
j--;
increase();
}
@Override
public void run() {
for (int j = 0; j < 1000000; j++) {
// this,当前实例对象锁
synchronized (this) {
i++;
reduce();// synchronized的可重入性
}
}
}
public static void main(String[] args) throws InterruptedException {
Thread t1 = new Thread(instanceImpl);
Thread t2 = new Thread(instanceImpl);
t1.start();
t2.start();
t1.join();
t2.join();
System.out.println("i:"+i);
System.out.println("j:"+j);
}
}

结果:

i:2000000
j:0

结果:
i:2000000
j:0

Synchronized之四:Synchronized的可重入性的更多相关文章

  1. Java多线程:synchronized的可重入性

    从Java多线程:线程间通信之volatile与sychronized这篇文章中我们了解了synchronized的基本特性,知道了一旦有一个线程访问某个对象的synchronized修饰的方法或代码 ...

  2. JAVA锁的可重入性

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

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

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

  4. Labview-vi的可重入性

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

  5. 三十三、Linux 进程与信号——中断系统调用和函数可重入性

    33.1 中断系统调用 进程调用 “慢” 系统调用时,如果发生了信号,内核会重启系统调用. 慢系统调用 可能会永久阻塞的系统调用 从终端设备.管道或网络设备上的文件读取 向上述文件写入 某些设备上的文 ...

  6. malloc的可重入性和线程安全分析

    malloc函数是一个我们经常使用的函数,如果不对会造成一些潜在的问题.下面就malloc函数的线程安全性和可重入性做一些分析. 我们知道一个函数要做到线程安全,需要解决多个线程调用函数时访问共享资源 ...

  7. java synchronized内置锁的可重入性和分析总结

    最近在读<<Java并发编程实践>>,在第二章中线程安全中降到线程锁的重进入(Reentrancy) 当一个线程请求其它的线程已经占有的锁时,请求线程将被阻塞.然而内部锁是可重 ...

  8. synchronized关键字的可重入性

    /**父类*/public class SynchronizedDemo1 implements Runnable { @Override public void run() { try { meth ...

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

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

随机推荐

  1. css可见性

    overflow:hidden:       溢出隐藏 visibility:hidden:        隐藏元素,隐藏之后还占据原来的位置 display:none:            隐藏元 ...

  2. 【kotlin】kotlin中List中添加List怎么操作

    如题,List集合添加一个List集合怎么操作 如上,现在有了List<A>,A类中有个字段List<B>, 新创建一个List<B>,想把LIst<A> ...

  3. MySQL安装总是失败,提示缺少Visual Studio 2013 Redistributable

    MySQL安装总是失败,提示缺少Visual Studio 2013 Redistributable,但是很疑惑,我明明已经安装了呀,原来问题出在版本上,以下提供了一个可以匹配新版本mysql的版本: ...

  4. 读取xml生成lua測试代码

    #include <iostream> #include <string> #include <fstream> #include "tinyxml2.h ...

  5. RESTful Web Service

  6. Adobe Flash builder破解方法

    Flash Builder 4 有许多新的特性,可以结合新的功能使用新的Flex 4框架创建出更炫的应用.基于用户的反馈,对以数据中心的开发也进行了优化:对类如配置从服务器返回的数据类型这样的任务,也 ...

  7. HTML制作练习

  8. string方法 PadLeft 返回一个新字符串,该字符串通过在此实例中的字符左侧填充指定的 Unicode 字符来达到指定的总长度,从而使这些字符右对齐。 PadRight 右边

  9. google protocol buffer的原理和使用(一)

    一.简单的介绍      Protocol buffers是一个用来序列化结构化数据的技术,支持多种语言诸如C++.Java以及Python语言.能够使用该技术来持久化数据或者序列化成网络传输的数据. ...

  10. 手动编译一个c文件(Win7下如何使用GCC编译器)

    主要参考这篇http://jingyan.baidu.com/article/c275f6bacc0126e33c756771.html 我没找到minGW的下载地址,而是直接用codeblocks自 ...