What is the difference between synchronized on lockObject and using this as the lock?

36,052

Solution 1

Personally I almost never lock on "this". I usually lock on a privately held reference which I know that no other code is going to lock on. If you lock on "this" then any other code which knows about your object might choose to lock on it. While it's unlikely to happen, it certainly could do - and could cause deadlocks, or just excessive locking.

There's nothing particularly magical about what you lock on - you can think of it as a token, effectively. Anyone locking with the same token will be trying to acquire the same lock. Unless you want other code to be able to acquire the same lock, use a private variable. I'd also encourage you to make the variable final - I can't remember a situation where I've ever wanted to change a lock variable over the lifetime of an object.

Solution 2

I had this same question when I was reading Java Concurrency In Practice, and I thought I'd add some added perspective on the answers provided by Jon Skeet and spullara.

Here's some example code which will block even the "quick" setValue(int)/getValue() methods while the doStuff(ValueHolder) method executes.

public class ValueHolder {
    private int value = 0;

    public synchronized void setValue(int v) {
        // Or could use a sychronized(this) block...
        this.value = 0;
    }

    public synchronized int getValue() {
        return this.value;
    }
}

public class MaliciousClass {

    public void doStuff(ValueHolder holder) {
        synchronized(holder) {
            // Do something "expensive" so setter/getter calls are blocked
        }
    }
}

The downside of using this for synchronization is other classes can synchronize on a reference to your class (not via this, of course). Malicious or unintentional use of the synchronized keyword while locking on your object's reference can cause your class to behave poorly under concurrent usage, as an external class can effectively block your this-synchronized methods and there is nothing you can do (in your class) to prohibit this at runtime. To avoid this potential pitfall, you would synchronize on a private final Object or use the Lock interface in java.util.concurrent.locks.

For this simple example, you could alternately use an AtomicInteger rather than synchronizing the setter/getter.

Solution 3

Item 67 of Effective Java Second Edition is Avoid excessive synchronization, thus I would synchronize on a private lock object.

Solution 4

Every object in Java can act as a monitor. Choosing one is dependent on what granularity you want. Choosing 'this' has the advantage and disadvantage that other classes could also synchronize on the same monitor. My advice though is to avoid using the synchronize keyword directly and instead use constructs from the java.util.concurrency library which are higher level and have well defined semantics. This book has a lot of great advice in it from very notable experts:

Java Concurrency in Practice http://amzn.com/0321349601

Share:
36,052
GantengX
Author by

GantengX

Self-proclaimed awesome full stack engineer who loves to build high quality products and also a certified barista. Currently my interest lies in Distributed Systems, Machine Learning, Adtech industry, Clojure and Go. I'm also experienced in JavaScript, Java, and various web frameworks such as Ember, React/Redux, Angular, and Backbone. I'm also a father to two cute and weird sons.

Updated on July 09, 2022

Comments

  • GantengX
    GantengX almost 2 years

    I know the difference between synchronized method and synchronized block but I am not sure about the synchronized block part.

    Assuming I have this code

    class Test {
      private int x=0;
      private Object lockObject = new Object();
    
      public void incBlock() {
        synchronized(lockObject) {
          x++;
        }
        System.out.println("x="+x);
      }
    
      public void incThis() {  // same as synchronized method
        synchronized(this) {
          x++;
        }
        System.out.println("x="+x);
      }
    }
    

    In this case what is the difference between using lockObject and using this as the lock? It seems to be the same to me..

    When you decide to use synchronized block, how do you decide which object to be the lock?

  • GantengX
    GantengX over 13 years
    I understand that it's not a proper synchronization since it uses different lock for different method, I'm just trying to understand the difference between using 'this' and 'lockObject' for the lock
  • Parth
    Parth over 13 years
    can you elaborate more? Say class A having instance of Class B. Now B has some member variable. When A calls any method of B, it gets lock on this/instance member...right? Means gets lock on instance of B itself or its member... can u just explain the difference?
  • Gopi
    Gopi over 13 years
    oh.. sorry for misunderstanding your question. So for that, the answer would be same as what Jon Skeet has answered.
  • Jon Skeet
    Jon Skeet over 13 years
    @Paarth: Your comment isn't clear - do you mean should B lock on the private lock for every method? That depends on the purpose of the class itself. Most classes don't need to try to be thread-safe at all, to be honest.
  • Parth
    Parth over 13 years
    yah, so i it needs to make sync method, it shuold use private member object instead of 'this' ... right? ok...
  • Maheshwar Ligade
    Maheshwar Ligade about 8 years
    synchronised(new Object ) vs synchronised(this ) what is the actual difference between this two, when to use which one
  • Jon Skeet
    Jon Skeet about 8 years
    @MaheshwarLigade: You should never create a new object just for a single synchronized block like that - there'd be no other code that could synchronize against the same object. You'd normally create a final variable within the class, e.g. private final Object lock = new Object(); and synchronize against that instead. That's better than synchronizing against this as you know that only your code has access to that monitor to synchronize on it.
  • try-catch-finally
    try-catch-finally over 6 years
    It does not answer the question (use synchronized or Locks), no real explanation, broken link (archived version). Downvoted.