sot*_*otn 4 java concurrency locking reentrancy
下面是一些用于"实践中的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();
}
}
Run Code Online (Sandbox Code Playgroud)
本书解释说,在上面的代码中......"因为Widget和LoggingWidget中的doSomething方法都是同步的,所以每个方法都会在继续之前尝试获取Widget上的锁定."
我运行上面的代码来观察内在锁.上面的引用似乎暗示一个线程获取Widget对象的内部锁,但我观察到的是该线程获取了LoggingWidget上的锁.我不确定如何验证采集计数,所以无法观察到.
该书是否可以互换地使用名称LoggingWidget/Widget,还是应该特意观察Widget对象的锁定?
编辑:完整摘录
重入有助于封装锁定行为,从而简化了面向对象的并发代码的开发.如果没有重入锁,代码中非常自然的代码(其中子类重写synchronized方法然后调用超类方法)将会死锁.因为Widget和LoggingWidget中的doSomething方法都是同步的,所以每个方法都会在继续之前尝试获取Widget上的锁.但是如果内部锁不是可重入的,那么对super.doSomething的调用将永远无法获取锁,因为它将被认为已经被保持,并且线程将永久停止等待它永远无法获取的锁.在这样的情况下,可重入使我们免于死锁.
我需要看一段摘录给你一个具体的答案.您可以以不同的方式实例化这些类.锁定在对象上,因此引用无关紧要.为了说明......
这个类结构非常类似于你的.
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();
}
}
Run Code Online (Sandbox Code Playgroud)
运行此程序并在使用您喜欢的方法(例如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
Run Code Online (Sandbox Code Playgroud)
由于此方法是成员变量,因此锁定位于this执行相关方法的当前对象()上.注意两个锁是如何打开的Sub@4c767286.
[编辑]
编辑我的答案以适合您的具体情况.
小智 5
是的,作者可以互换使用LoggingWidget / Widget,因为根据OOP继承原理,LoggingWidget对象也是Widget类对象。在该示例中,将仅创建一个对象实例,并将其用作同步监视器以重新输入。
| 归档时间: |
|
| 查看次数: |
873 次 |
| 最近记录: |