继承与可重入锁
可重入锁在继承情况下super锁住的是谁。关于这个问题,设计了一个Demo
1 | // 父类 |
如果上面代码似曾相识,好像在哪里见过,不用怀疑,我就是从《Java并发编程实战》里摘下来的。至于为什么呢?因为我对里面有些地方表示疑惑。
问:子类重写了父类的doSomething方法,然后通过super去调用父类的doSomething方法,那么在父类同步锁的doSomething方法里锁住的是谁?是父类Widget吗,还是子类LoggingWidget?
为此,通过Demo来说话吧
Demo
尝试直接在父类同步方法里打印
对比代码
对比代码:
这里先直接new一个父类去调用他的方法,来看看父类方法中的this(即锁的是什么)
代码结果:
我们可以看到直接调用父类方法,不出意外都是会打印出自个儿的类的地址。那么下面我们看看通过super去调用又会怎样。
实验代码
实验代码:
运行结果:
从结果可以看出 先打印 “子类 - doSomething” 再打印 “父类 - doSomething” 最后打印出锁住的对象 “thread.LoggingWidget@74a14482”。这里打印出的是子类的地址。对比我们的对比代码中的结果,我们可以很轻易地得出 在一个得到了锁的方法里通过使用super去调用父类的同步方法,那么父类同步方法中被锁住的是子类对象,其父类并没有被锁住
结论
在《Java并发编程实战》里关于重入锁的描述中有个不那么严谨的说法:由于Widget和LoggingWidget中doSometimes方法都是Synchronized方法,因此每个doSomething方法在执行前都会获取Widget上的锁。关于这个,通过一些简单的Demo,现在知道,调用一个Synchronized方法,Synchronized锁住的是调用的对象(即子类),而在这个Synchronized方法里通过super调用父类的同步方法,父类同步方法锁住的也是子类对象