java 可重入锁

一 什么是可重入锁?


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

        通俗来说:当线程请求一个由其它线程持有的对象锁时,该线程会阻塞,而当线程请求由自己持有的对象锁时,如果该锁是重入锁,请求就会成功,否则阻塞。在java中,可重入锁分为两种,即synchronized锁以及ReentrantLock及其实现。重入锁就是一个线程能否获取一个已经由它自己持有的锁。如果可以,就是可重入锁,否则为不可重入锁。它的作用就是能够避免重复获取的时候出现死锁。


public class ReentrantSynchronizer {
    public synchronized void print() {
        System.out.println(Thread.currentThread().getName());
        printf();
    }

    public synchronized void printf() {
        System.out.println(Thread.currentThread().getName());
        print();
    }

    public static void main(String[] args) {
        ReentrantSynchronizer reentrantSynchronizer = new ReentrantSynchronizer();
        for (;;){
            reentrantSynchronizer.print();
        }
    }
}
以上的demo就是测试synchronized的可重入性质,方法一中调用方法二,方法二又调用方法一

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


二 可重入锁的实现原理?

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


三 总结

  • 可重入锁、不可重入锁,针对的对象是同一线程
  • 对于可重入锁,获取了该锁的线程可以重复获取该锁,不会造成死锁。
  • 而不可重入锁,获取该锁的线程再获取该锁的时候,会等待对方释放,造成死锁
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值