Static versus non-static lock object in synchronized block

27,835

The difference is simple: if the locked-on object is in a static field, then all instances of MyClass* will share that lock (i.e. no two objects will be able to lock on that object at the same time).

If the field is non-static, then each instance will have its own lock, so only calls of the method on the same object will lock each other.

When you use a static lock object:

  • thread 1 calls o1.foo()
  • thread 2 calls o1.foo(), will have to wait for thread 1 to finish
  • thread 3 calls o2.foo(), will also have to wait for thread 1 (and probably 2) to finish

When you use a non-static lock object:

  • thread 1 calls o1.foo()
  • thread 2 calls o1.foo(), will have to wait for thread 1 to finish
  • thread 3 calls o2.foo(), it can just continue, not minding thread 1 and 2

Which one of those you'll need depends on what kind of data you try to protect with your synchronized block.

As a rule of thumb, you want the lock-object to have the same static-ness than the operated-on value. So if you manipulate non-static values only, you'll want a non-static lock object. If you manipulate static values only, you'll want a static lock object.

When you manipulate static and non-static values, then it'll become complicated. The easy way would be to just use a static lock object, but that might increase the size of the synchronized-block more than absolutely necessary and might need to more lock contention than desired. In those cases you might need a combination of static and non-static lock objects.

In your particular case you use the lock in the constructor, which will only ever be executed once per instance, so a non-static lock-object doesn't make any sense here.

Share:
27,835
ADTC
Author by

ADTC

As I move around the site, cleaning up after you, tidying up the mess you leave, you don't notice me. But that's okay. I like it clean. I like it smelling fresh. And that's why I'm the janitor. Tools in my arsenal:   - Add kbd shortcut   - Edit summary options (hacked)   - Indentation using Tab key   - Keyboard shortcuts for comments Rule of thumb for robust source code: Never assume this line will work as intended when writing the next. Be prepared for surprises. This is me when I'm working: 26MB for $4,995?! IT'S A STEAL!!!

Updated on December 10, 2020

Comments

  • ADTC
    ADTC over 3 years

    Trying to visualize and understand synchronization.

    1. What are the differences between using a static lock object (code A) and a non-static lock object (code B) for a synchronized block?
    2. How does it differ in practical applications?
    3. What are the pitfalls one would have that the other wouldn't?
    4. What are the criteria to determine which one to use?

    Code A

    public class MyClass1 {
      private static final Object lock = new Object();
      public MyClass1() {
        //unsync
        synchronized(lock) {
          //sync
        }
        //unsync
      }
    }
    

    Code B

    public class MyClass2 {
      private final Object lock = new Object();
      public MyClass2() {
        //unsync
        synchronized(lock) {
          //sync
        }
        //unsync
      }
    }
    

    Note

    The above code shows constructors, but you could talk about how the behavior is different in a static method and a non-static method too. Also, would it be advantageous to use a static lock when the synchronized block is modifying a static member variable?

    I already looked at answers in this question, but it's not clear enough what the different usage scenarios are.

  • ADTC
    ADTC over 10 years
    I think using the constructor as an example was a bad idea. Anyway, good answer. I want to ask one more question. Is there a way of ensure that a set of methods operating on a volatile static member variable via one thread will be done and over with before other threads access this member variable? I can make this a separate question on SO if necessary.
  • Joachim Sauer
    Joachim Sauer over 10 years
    @ADTC: that does sound like a separate question to me. Short answer: no, you'll need synchronization. You can avoid it only if the operation of the volatile is atomic (for example a single ++ on an int**and** you don't care about the order (i.e. you don't care if you read before or after the operation).
  • ADTC
    ADTC over 10 years
    I do care about the read, it should only happen after the operation. I think I will ask it as a separate question.
  • Joachim Sauer
    Joachim Sauer over 10 years
    @ADTC: actually, I mis-informed you: even x++ isn't atomic on a volatile x. Do go ahead and ask a new question for this.
  • Hussain Akhtar Wahid 'Ghouri'
    Hussain Akhtar Wahid 'Ghouri' almost 10 years
    if two threads are accessing same object's two diff non-static methods , it is possible or the second thread has to wait , does the lock on one object locks all non-static methods ??
  • Asif Mushtaq
    Asif Mushtaq over 8 years
    @HussainAkhtarWahid'Ghouri' Yes, each thread(accessing same object resources) need to wait until other thread leave lock on any same-instance-synchronized-method.