Overriding synchronized methods in Java
Asked Answered
M

2

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)?
Maxinemaxiskirt answered 12/3, 2013 at 23:53 Comment(2)
See #12685350Erund
bugs.sun.com/bugdatabase/view_bug.do?bug_id=4294756 Synchronized is not part of the method signature, but part of the method implementation.Mondragon
A
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.

Ankerite answered 12/3, 2013 at 23:56 Comment(4)
using fooImpl is the correct way and still reminds me ClassLoader.loadClassInternal Of course one can cheat in fooImpl via monitorExit / moniorEnterBulwark
@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.Ankerite
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.Bulwark
Found it: Structured locking which is non-mandatory. It appears the term is coined w/ java se7 or at least could not find previous references.Bulwark
L
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

Louanne answered 13/3, 2013 at 0:13 Comment(1)
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).Balanchine

© 2022 - 2024 — McMap. All rights reserved.