0

I'm trying to understand the exact differences in synchronisation using:

  1. synchronized(MyClass.class){...}

  2. synchronized(myClassInstance.getClass()){...} [edited as MyClass.getClass() doesn't even compile]

  3. synchronized(this){...}

Thanks to other posts I get that (1) is used to make sure that there is exactly one thread in the block and that (3) ensures that there is exactly one thread per instance.

(see Java Synchronized Block for .class )

But what does (2) do? Is it identical to (3)?

Maarten Bodewes
  • 90,524
  • 13
  • 150
  • 263
mayool
  • 138
  • 8
  • 4
    (1) Synchronizes on the `Class`, (2) Doesn't compile: you are using an instance method in a static context, (3) Synchronizes on the instance. – Slaw Aug 14 '18 at 10:33
  • #2 would work if you would write `myClassInstance`, but in that case it would be identical to #1; the class is just referenced differently (that is, if `myClassInstance` is not an instance of a derived class instead of the base class). – Maarten Bodewes Aug 14 '18 at 10:39
  • #2 could also at least compile with `MyClass.class.getClass()`, couldn't it? – Clijsters Aug 14 '18 at 10:40
  • @Clijsters No, that would be the class of a class instance, which would probably be the same for any class (`class java.lang.Class` of course). Well, it would work: it would lock the same way as #1 I presume, but setting a lock on something that is not local is not recommended. – Maarten Bodewes Aug 14 '18 at 10:47
  • I just did it and it compiled. As you edited your comment: I just said it would compile, not it would make sense, nor that it's recommended ;) – Clijsters Aug 14 '18 at 10:47

2 Answers2

1

You mention you already understand options #1 and #3 so I'll focus on option #2.

As I state in the question comments, option #2 doesn't compile as written. However, I believe your intent is to obtain the class in an instance fashion rather than a static fashion (MyClass.class).

public class MyClass {

    public void foo() {
        synchronized (MyClass.class) {
        }
    }

    public void bar() {
        synchronized (getClass()) {
        }
    }

}

In the above code both MyClass.class and getClass() return the same object which means they are "equivalent". However, you have to be careful here.

public class MySubClass extends MyClass {
    // inherits methods...
}

Now the two methods (foo and bar) are not equivalent. The method foo still uses the Class of MyClass to synchronize but bar now uses the Class of MySubClass (i.e. they are no longer synchronizing on the same object).

Slaw
  • 37,820
  • 8
  • 53
  • 80
0

Point 1 will take the lock on the Class Object and only one object can exists (if the same class is not loaded by different classloaders ) in the JVM. This can be used with Static as well as noon static methods

Second option will not compile.

Third Option will take the locks on the current object. Third option can be used with instance method as this can be used in case of static methods.

Dinesh
  • 1,046
  • 1
  • 8
  • 17