zoukankan      html  css  js  c++  java
  • synchronized的可重入性

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

    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,则释放该锁。

  • 相关阅读:
    《C# to IL》第一章 IL入门
    multiple users to one ec2 instance setup
    Route53 health check与 Cloudwatch alarm 没法绑定
    rsync aws ec2 pem
    通过jvm 查看死锁
    wait, notify 使用清晰讲解
    for aws associate exam
    docker 容器不能联网
    本地运行aws lambda credential 配置 (missing credential config error)
    Cannot connect to the Docker daemon. Is 'docker daemon' running on this host?
  • 原文地址:https://www.cnblogs.com/govoid/p/5396348.html
Copyright © 2011-2022 走看看