7

People tell about two types of multi-threaded locking - object and class. In my knowledge, locking is done on objects only.

Case 1: On objects we create using new or factory methods etc.

void synchronized myMethod(Type param) {
  //will lock on the instance used to call this method
}

or

synchronized(this) {
 //will lock on current object
}

or

synchronized(obj1) {
 //will lock on specified obj1 object
}

Case 2: On java.lang.Class objects

This is called class lock, and can be used with static fields or methods or blocks, as they belong to class and shared among all the objects, and other class properties.

static void synchronized method() {
  //will lock the Class object
}

or

static {
  synchronized(SomeClass.class){
    int a = 2;
  }
}
  • Why I am thinking this also as an object locking because classes are loaded into the Method Area in the JVM, and all the static properties of the class are wrapped inside a java.lang.Class object created by JVM. So behind abstraction, its object locking and in the picture, we see Class locking.
  • So I can also infer one more thing. Just as objects locked by a thread can not be acquired by another thread as long as it is not released by first thread, class locking (the java.lang.Class instance) also works in same manner.
  • I want to know in case of synchronized static methods, lock on which class is acquired by the thread in following two cases:

    1. This method is called from same class where it is defined.
    2. This method is called from derived class with derived class name.

This is my understanding so far regarding the subject. Please add on or rectify.

xploreraj
  • 3,792
  • 12
  • 33
  • 51

2 Answers2

9

People tell about two types of multi-threaded locking - object and class.

A Class is an Object. There is only one kind of locking in the Java language: Every Object (including every Class) has a mutex that can be locked by a synchronized block or a synchronized method. The Object to be locked is implicit in a synchronized method: It's the "this" instance for an instance method, and it's the Class object for a static method.

One of the most common newbie mistakes is to think that two different threads can't get into the same synchronized block at the same time. They can, and there's plenty of questions and answers here in StackOverflow that prove it. Another mistake is to think that if one thread is synchronized on some object, then other threads will not be able to modify the object. They can and they do.

Synchronization prevents two or more threads from synchronizing on the same Object at the same time. Which object is the right object? It's all about protecting your data. If the structure that you want to protect is a linked list, for example, then a good choice would be for any method that accesses the list to synchronize on the list header. If you want to protect global data (e.g., static variables), then you want to synchronize on a global object (e.g., the Class object that owns the variables.) The important thing is that, if you have read/write data (a.k.a., "mutable data") that are accessed by more than one thread, then every method that accesses the same data must synchronize on the same lock.


There is another kind of locking in Java, but it's not in the Java language; it's in the Java standard library. It's available through objects that implement the java.util.concurrent.locks.Lock interface. Of course a Lock object (like any Object) also implements the first kind of locking, but you should never, ever, synchronize on a Lock object unless you want to give people the impression that you are a clueless newbie.

The java.util.concurrent-style locking is more powerful than using synchronized blocks because of it's explicit lock() and unlock() methods. For example, it is possible for one method to lock a lock, and a different method to unlock it. That can lead to code that is tricky to understand, and I wouldn't do it unless I had a very good reason, but sometimes there are good reasons.

Solomon Slow
  • 25,130
  • 5
  • 37
  • 57
  • Yes. Thanks for the info :) Gradually I will start with the concurrent package! But is this required for non-multithreading job related Java interviews? – xploreraj Apr 24 '14 at 14:14
  • "if one thread is synchronized on some object, then other threads will not be able to modify the object " how come ? doesn't it violate the entire synchronization technique. –  Jun 06 '17 at 07:10
  • @HarishAmarnath https://stackoverflow.com/questions/24068672/how-is-class-level-locking-achieved-in-java/24069242#24069242 – Solomon Slow Jun 06 '17 at 13:53
  • 1
    @jameslarge , yes i understood that if a static synchronized method is called using object reference and class instance at the same time...it **will execute at the same time** . but imagine passing a same objects to two different thread ... its only until any one of the thread meets the synchronized block the object is synchronized and unable to be modified right? untill then the object is shared among threads right? –  Jun 06 '17 at 17:11
  • 3
    @HarishAmarnath, the object is _never_ unable to be modified. A `synchronized (foo)` block does not stop other threads from modifying `foo`: It only stops other threads from entering a `synchronized (foo)` block. – Solomon Slow Jun 06 '17 at 17:13
  • Got it all except one thing about the class locking. Firstly, if my class has static sync methods, then would calling only one out of all these methods lock the entire class? If yes, then would I be still able to access non-static properties of the class. Secondly, the object that gets locked to a thread when the thread enters a static synchronized block is the **SomeClass.class object** (subclass of Object class, say, my custom class) or the main **java.lang.Class** object? – Aakash Verma Nov 06 '17 at 10:35
  • @AakashVerma, See this answer for what `static synchronized` really means: https://stackoverflow.com/a/26676499/801894 – Solomon Slow Nov 06 '17 at 14:35
  • 1
    @AakashVerma, Re, "...would I be still able to access non-static properties of the class...?" A `synchronized(foobar) {...}` block does _not_ prevent other threads from accessing the fields of `foobar`. The only thing it prevents is, it prevents other threads from synchronizing on the same object at the same time. If you don't want your threads A, B, and C to access the fields of `foobar` while thread D has `foobar` locked, then it's up to _you_ to ensure that they only access `foobar` from inside `synchronized(foobar)` blocks. – Solomon Slow Nov 06 '17 at 14:38
4

The only difference is that a static synchronized locks on the class instance and a non-static synchronized method locks on the instance.

People tell about two types of multi-threaded locking

There is object instance locks and Lock style locks. A Lock, confusingly, has both.

object and class

Not true as you have worked out already.

Just because people say stuff doesn't make it true. Often people say a lot of nonsense. In fact there is whole web sites devoted to non-sense about Java. :P

Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130
  • 1
    Consider two classes: `class A` and `class B extends A`. A has method `static synchronized int add()`. Now from B class, if I call `B.add()`, it will lock B class object right, and if I call `A.add()`, A class object will be locked right? And when B class object is locked, another thread can not modify other B static fields or methods etc.,. if they are synchronized. If not synchronized, can be modified by any number of threads simultaneously? – xploreraj Apr 24 '14 at 07:25
  • 1
    @xploreraj There is no B.add(), only an A.add() so A.class will be locked. You new call new B().add() but it will still lock A.class. When you lock B.class, another thread cannot lock B.class, but it can access anything else it can e.g. methods and fields. If not synchronized, or `Lock`ed there is no restriction on multiple threads performing multiple writes/reads. – Peter Lawrey Apr 24 '14 at 07:46
  • _You new call `new B().add()` but it will still lock A.class._ `add()` is static method in base class, so I can directly do `B.add()`. It locks `A.class` because the method is in A, irrespective of the caller. If in same case `add()` was also defined in B class, then it would have locked `B.class`. Correct me! Thanks Peter :) – xploreraj Apr 24 '14 at 09:05
  • 2
    @xploreraj Correct. You could have A.add() *and* B.add(), both static and synchronized. If B.add() calls A.add() and you call B.add() both B.class and then A.class would get locked. – Peter Lawrey Apr 24 '14 at 10:17
  • And this clears my doubt. Thanks. I am marking this as answer, although any more reviews or knowledge is eagerly awaited. **I think I have covered thread synchronization basics completely here.** – xploreraj Apr 24 '14 at 10:21
  • 1
    @xploreraj - The key thing is that there is no overwriting/polymorphism on static methods. So B.add is simply providing access to A.add. So the only lock would be on A. – Brett Okken Apr 24 '14 at 14:10
  • As per method hiding, I don't think that unless and until B.add() calls A.add() internally and explicitly in its code, there would be any lock performed on A.add(), considering we have implemented add() in B again. If it's just calling the inherited add() in B, I believe what Peter said is right about both the classes getting locked (still, somehow I feel it's only A that would be locked) – Aakash Verma Nov 06 '17 at 10:07