以下是来自“Java并发性实践”的可重入锁定的一些示例代码:
class Widget {
public synchronized void doSomething() {
System.out.println(toString() + ": calling superclass doSomething");
}
}
class LoggingWidget extends Widget {
public synchronized void doSomething() {
System.out.println(toString() + ": calling subclass doSomething");
super.doSomething();
}
}这本书解释说在上面的代码中..。因为Widget和LoggingWidget中的LoggingWidget方法都是同步的,所以在继续之前,每个方法都试图获取Widget上的锁。
我运行了上面的代码来观察内部锁。上面的引号似乎意味着线程在Widget对象上获得了一个内在锁,但我观察到的是线程在LoggingWidget上获得了一个锁。我不知道如何核实收购数量,所以无法观察到这一点。
这本书是交替使用LoggingWidget/Widget的名称,还是应该具体地观察Widget对象上的锁?
编辑:完整摘录
可重入性简化了锁定行为的封装,从而简化了面向对象并发代码的开发.如果没有重入锁,清单2.7中非常自然的代码(在清单2.7中,子类重写同步方法,然后调用超类方法)将导致死锁。因为Widget和LoggingWidget中的LoggingWidget方法都是同步的,所以在继续之前,每个方法都尝试获取Widget上的锁。但是,如果内部锁不是可重入的,那么对super.doSomething的调用将永远无法获得锁,因为它将被视为已持有,并且线程将永久停止等待它永远无法获得的锁。在这种情况下,可重入性可以帮助我们避免陷入僵局。
发布于 2015-01-12 11:48:16
是的,作者交替使用LoggingWidget/Widget,因为根据OOP继承原则,LoggingWidget对象也是Widget类对象。在该示例中,将只创建一个对象实例,并将其用作重新输入的同步监视器。
发布于 2015-01-12 11:36:15
我需要看摘录才能给你一个具体的答案。您可以以不同的方式实例化这些类。锁被保存在对象上,所以引用是什么并不重要。为了说明..。
这个类结构与你的非常相似。
public class GenericTest {
public static void main(String... args) {
Sub sub = new Sub();
sub.go();
}
public synchronized void go() {
System.out.println("Parent");
}
}
class Sub extends GenericTest {
@Override
public synchronized void go() {
System.out.println("Child");
super.go();
}
}运行此程序,并在使用您满意的方法(例如System.in.read())获取锁后停止执行进一步的行。查找java程序的pid并在Jconsole中打开它。移动到threads部分,并在每次获得锁时突出显示它。你会看到下面的痕迹。
my.package.common.GenericTest.go(GenericTest.java:30)
- locked my.package.common.Sub@4c767286
my.package.common.Sub.go(GenericTest.java:42)
- locked my.package.common.Sub@4c767286由于此方法是一个成员变量,所以锁位于执行该方法的当前对象(this)上。请注意两个锁是如何在Sub@4c767286上的。
编辑
根据你的具体情况编辑了我的答案。
https://stackoverflow.com/questions/27900332
复制相似问题