Is synchronized inherited in Java?
Asked Answered
L

3

33

I have superclass Point and a synchronized method draw(). Will the subclasses of Point inherit synchronized if I override method draw() in them or I have to always write it?

Lex answered 14/4, 2013 at 11:3 Comment(1)
possible duplicate of Overriding a synchronized methodGradus
C
32

No, you will always have to write synchronized. If you call the synchronized method of the super class this will of course be a synchronized call. synchronized is not part of the method signature.

See http://gee.cs.oswego.edu/dl/cpj/mechanics.html for detailed description from Doug Lea, Java threading boss (or so).

Crowns answered 14/4, 2013 at 11:14 Comment(3)
Maybe clarify one detail: whether or not a given method call is synchronized depends on the dynamic type of the object it's called on, not the static type. That is, if foo() is synchronized in Derived but not in Base, and you assign a Derived to a Base variable and call foo() on it, that call will be synchronized. This point is implicit in 8.4.3.6 of the language spec (which says a synchronized method is equivalent to a synchronized statement within that method), but I couldn't find it spelled out anywhere else. Runnable demo here.Burglarize
Will calling super.draw() be still synchronized?Obeisance
If super.draw() is synchronised, then of course it will.Crowns
G
8

You can check it yourself by writing this:

public class Shape {

    protected int sum = 0;

    public synchronized void add(int x) {
        sum += x;
    }
}


public class Point extends Shape{

    public void add(int x) {
        sum += x;
    }

    public int getSum() {
        return sum;
    }
}

And test class

public class TestShapes {

    public final static int ITERATIONS = 100000;

    public static void main(String[] args) throws InterruptedException {

        final Point p = new Point();

        Thread t1 = new Thread(){
            @Override
            public void run() {

                for(int i=0; i< ITERATIONS; i++){
                    p.add(1);
                }
            }
        };

        Thread t2 = new Thread(){
            @Override
            public void run() {

                for(int i=0; i< ITERATIONS; i++){
                    p.add(1);
                }
            }
        };

        t1.start();
        t2.start();

        t1.join();
        t2.join();


        System.out.println(p.getSum()); // should equal 200000

    }
}

On my machine it was 137099 instead of 200000.

Genuflection answered 14/4, 2013 at 11:20 Comment(4)
easier way to test would be to test on Thread.holdsLock(this); in the overridden methodStruck
Doesn't answer the question. Test code could just expose a bug or a time anomaly due to something other than synchronization. The answer is to be found in the language specification.Malarkey
@EJP At first I thought you were wrong. Then I realized you were actually right, but rather pessimistic...Enamour
I seriously discourage anyone from exploring like this. Your test might be correct in most cases but miss a very specific but very important aspect - and you'd never know until it bites you. Instead, READ THE SPECIFICATION! - then you know.Midget
T
5

your Overriden method will no longer be synchronized if you Override it and remove the synchronized. Found it here and here

Turnabout answered 14/4, 2013 at 11:13 Comment(1)
Neither of your citations is a normative reference.Malarkey

© 2022 - 2024 — McMap. All rights reserved.