Why can't an abstract method be synchronized?

13,019

Solution 1

The comment about not being able to instantiate the abstract class is garbage. Given that it has to be an instance method to be abstract, there certainly is a reference which could be locked on. Concrete methods in abstract classes can still refer to this. However, that still doesn't mean that abstract classes should be able to be synchronized.

Whether or not a method is synchronized is an implementation detail of the method. Synchronization isn't specified anywhere as a declarative contract - it's not like you can synchronize in interfaces, either.

How a class implements whatever thread safety guarantees it provides is up to it. If an abstract class wants to mandate a particular approach, it should use the template method pattern:

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

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

protected abstract void fooImpl();

That's pretty dangerous in itself though, given that it's effectively calling "unknown" code within a lock, which is a recipe for deadlocks etc.

Solution 2

Locking behavior shouldn't be specified using abstract methods or interface methods because it shouldn't be part of the contract.

Probably the idea was that locking behavior is fundamentally part of the implementation -- different implementations will want to perform locking differently -- and it would be counterproductive to specify it at that level of abstraction.

Remember the keyword synchronized is specifically for implementing implicit locking (acquiring the lock on the object that the instance method is called on), and there are ways to do locking using alternatives like ReentrantLock, where that keyword is not applicable, or possibly to use CAS or otherwise avoid locking altogether.

Solution 3

synchronized void foo()
{
    body
}

is defined to be equivalent to

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

(if static, synchronized on the class instead of this)

Since an abstract method has no body, synchronized keyword on the method is undefined.

Solution 4

I think one logic behind that could be that whether or not to synchronize that method should be decided by the implementing class. Meaning, it gives the freedom to the implementer to choose on whether to provide a synchronized or unsynchronized implementation. Plus, the client would also have option to to select the unsynchronized version so as to avoid synchronization overhead if thread-safety is not an issue.

Share:
13,019

Related videos on Youtube

ahodder
Author by

ahodder

I'm a derp who derps with herps in hopes that the herp does all the derping I want it to.

Updated on June 11, 2022

Comments

  • ahodder
    ahodder about 2 years

    I was reading a thread from CodeRanch saying that abstract methods could not be synchronized due to the fact that an abstract class cannot be instantiated, meaning no object to lock.

    This doesn't make sense since an abstract class is a definition (contract) for a child class. The abstract definition of a synchronized method does not need to lock, the child does. All the abstract heading would indicate is that the child must synchronize this method. Is my logic on this correct? If not can someone explain why I'm wrong?

    • biziclop
      biziclop over 11 years
      It was simply a design decision. It wasn't inevitable that it ended up this way, there are arguments pro and con. The argument that there's no object to lock on is clearly wrong though.
  • ahodder
    ahodder over 11 years
    Thanks for the clear answer. I didn't think about deadlocks when positing that an abstract class should support synchronized method calls.
  • Debdeep
    Debdeep about 5 years
    @jon-skeet Whether or not a method is synchronized is an implementation detail of the method- understand that it's not in a declarative contract but what If we want to enforce a certain implementation to be synchronized?
  • Jon Skeet
    Jon Skeet about 5 years
    @Debdeep: I'm not sure what you mean. If it's for a particular implementation, you just make sure the implementation does that. If you mean you want to enforce that every implementation of a particular abstract method is synchronized, you can't.