我正在阅读CodeRanch 的一个线程,说抽象方法无法同步,因为抽象类无法实例化,这意味着没有对象可以锁定。
这是没有意义的,因为抽象类是子类的定义(契约)。同步方法的抽象定义不需要锁,子进程需要。所有抽象标题都表明孩子必须同步此方法。我对此的逻辑正确吗?如果没有,有人可以解释为什么我错了吗?
我正在阅读CodeRanch 的一个线程,说抽象方法无法同步,因为抽象类无法实例化,这意味着没有对象可以锁定。
这是没有意义的,因为抽象类是子类的定义(契约)。同步方法的抽象定义不需要锁,子进程需要。所有抽象标题都表明孩子必须同步此方法。我对此的逻辑正确吗?如果没有,有人可以解释为什么我错了吗?
关于无法实例化抽象类的评论是垃圾。鉴于它必须是抽象的实例方法,所以肯定有一个可以锁定的引用。抽象类中的具体方法仍然可以引用this
. 但是,这仍然不意味着抽象类应该能够同步。
方法是否同步是该方法的实现细节。同步并没有在任何地方指定为声明性合同——你也不能在接口中同步。
一个类如何实现它提供的任何线程安全保证取决于它。如果一个抽象类想要强制使用特定的方法,它应该使用模板方法模式:
// I hate synchronizing on "this"
private final Object lock = new Object();
public final void foo() {
synchronized(lock) {
fooImpl();
}
}
protected abstract void fooImpl();
不过,这本身就很危险,因为它有效地调用了锁中的“未知”代码,这是导致死锁等的秘诀。
不应该使用抽象方法或接口方法来指定锁定行为,因为它不应该是契约的一部分。
可能的想法是锁定行为从根本上是实现的一部分——不同的实现会希望以不同的方式执行锁定——并且在该抽象级别指定它会适得其反。
请记住,该关键字synchronized
专门用于实现隐式锁定(获取调用实例方法的对象上的锁定),并且有一些方法可以使用 ReentrantLock 等替代方法进行锁定,其中该关键字不适用,或者可能使用 CAS 或否则完全避免锁定。
synchronized void foo()
{
body
}
被定义为等价于
void foo()
{
synchronized(this)
{
body
}
}
(如果是静态的,则在类上同步而不是this
)
由于抽象方法没有主体,synchronized
因此方法上的关键字未定义。
我认为这背后的一个逻辑可能是是否同步该方法应该由实现类决定。意思是,它让实现者可以自由选择是否提供同步或非同步实现。另外,如果线程安全不是问题,客户端还可以选择非同步版本以避免同步开销。