27

我正在阅读CodeRanch 的一个线程,说抽象方法无法同步,因为抽象类无法实例化,这意味着没有对象可以锁定。

这是没有意义的,因为抽象类是子类的定义(契约)。同步方法的抽象定义不需要锁,子进程需要。所有抽象标题都表明孩子必须同步此方法。我对此的逻辑正确吗?如果没有,有人可以解释为什么我错了吗?

4

4 回答 4

35

关于无法实例化抽象类的评论是垃圾。鉴于它必须是抽象的实例方法,所以肯定一个可以锁定的引用。抽象类中的具体方法仍然可以引用this. 但是,这仍然不意味着抽象类应该能够同步。

方法是否同步是该方法的实现细节。同步并没有在任何地方指定为声明性合同——你也不能在接口中同步。

一个类如何实现它提供的任何线程安全保证取决于它。如果一个抽象类想要强制使用特定的方法,它应该使用模板方法模式:

// I hate synchronizing on "this"
private final Object lock = new Object();

public final void foo() {
    synchronized(lock) {
        fooImpl();
    }
}

protected abstract void fooImpl();

不过,这本身就很危险,因为它有效地调用了锁中的“未知”代码,这是导致死锁等的秘诀。

于 2012-10-09T18:05:28.197 回答
9

不应该使用抽象方法或接口方法来指定锁定行为,因为它不应该是契约的一部分。

可能的想法是锁定行为从根本上是实现的一部分——不同的实现会希望以不同的方式执行锁定——并且在该抽象级别指定它会适得其反。

请记住,该关键字synchronized专门用于实现隐式锁定(获取调用实例方法的对象上的锁定),并且有一些方法可以使用 ReentrantLock 等替代方法进行锁定,其中该关键字不适用,或者可能使用 CAS 或否则完全避免锁定。

于 2012-10-09T18:02:56.913 回答
4
synchronized void foo()
{
    body
}

被定义为等价于

void foo()
{ 
    synchronized(this)
    {
        body
    }
}

(如果是静态的,则在类上同步而不是this

由于抽象方法没有主体,synchronized因此方法上的关键字未定义。

于 2012-10-09T18:06:29.140 回答
3

我认为这背后的一个逻辑可能是是否同步该方法应该由实现类决定。意思是,它让实现者可以自由选择是否提供同步或非同步实现。另外,如果线程安全不是问题,客户端还可以选择非同步版本以避免同步开销。

于 2012-10-09T18:06:37.743 回答