54

Let's say I have a synchronized method on some class:

abstract class Foo {
    public synchronized void foo() {  // synchronized!
        // ...
    };
}

and I overrode it without using the synchronized modifier:

class Bar extends Foo {
    @Override
    public void foo() {               // NOT synchronized!
        super.foo();
        // ...
    }
 }

I have a couple of specific question regarding this scenario:

  1. Will the overridden method be implicitly synchronized as well?
  2. If not, will the super-call be synchronized?
  3. If there is no super-call, will anything be synchronized?
  4. Is there a way to force an overriding method to use synchronized (I noticed that abstract method definitions or method definitions inside an interface don't allow the synchronized keyword)?
Markus A.
  • 12,349
  • 8
  • 52
  • 116
  • 1
    See http://stackoverflow.com/questions/12684850/how-can-i-ensure-that-an-overridden-method-is-synchronized – rgettman Mar 12 '13 at 23:57
  • 4
    http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4294756 Synchronized is not part of the method signature, but part of the method implementation. – flup Mar 13 '13 at 00:01

2 Answers2

58
public synchronized void foo() {  // synchronized!
    // ...
};

Is essentially the same as:

public void foo() {
    synchronized (this) {  // synchronized!
        // ...
    }
};

The latter is more explicit, so I would generally suggest using that form. Or better using a lock that is a private field instead of the "outer" object.

So: 1. No. 2. Yes. 3. No. 4. Mark the method final and call a protected method that may be overridden.

public final void foo() {
    synchronized (this) {
        fooImpl();
    }
};
protected void fooImpl() {
    // ...
}

As ever, you may well be better off with delegation rather than subclassing.

Tom Hawtin - tackline
  • 145,806
  • 30
  • 211
  • 305
  • using fooImpl is the correct way and still reminds me [ClassLoader.loadClassInternal](http://bugs.sun.com/view_bug.do?bug_id=4670071) Of course one can cheat in fooImpl via `monitorExit` / `moniorEnter` – bestsss Apr 21 '13 at 19:58
  • @bestss Even if you write your own bytecode, monitor enter/exit should be matched. (IIRC there's some peculiar leeway in the spec, but not any reasonable implementation.) Although `fooImpl` could `wait`. – Tom Hawtin - tackline Apr 21 '13 at 20:03
  • Unless it's rather new change (and you mean within the same method) it was not the case, even the biased locking had to take consideration of imbalanced enter/exit. If you call `wait` you'd need another thread to execute the code. Otherwise it's just calling in loop monitorExit till IllegalMonitorStateException and counting and then monitorEnter. Hmm, really have to check the spec. – bestsss Apr 21 '13 at 20:14
  • Found it: [Structured locking](http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-2.html#jvms-2.11.10) which is non-mandatory. It appears the term is coined w/ java se7 or at least could not find previous references. – bestsss Apr 21 '13 at 20:31
23

Failing to use synchronized when overriding a synchronized method has the potential for causing runtime bugs. As a safeguard, there is an Eclipse checker you can turn on to detect this condition. The default is "ignore". "Warning" is also a valid choice. preferences

which will produce this message:

enter image description here

enter image description here

Java42
  • 7,628
  • 1
  • 32
  • 50
  • Old answer, but you should explain your assertion that failing to synchronize an override can cause bugs. Explaining how to flag these in a development environment is interesting, but not an answer (to any question, let alone the OP's 4). – SensorSmith Sep 08 '21 at 23:15