What is the difference between synchronized on lockObject and using this as the lock?
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
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, 2022Comments
-
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 over 13 yearsI 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 over 13 yearscan you elaborate more? Say class
A
having instance of ClassB
. NowB
has some member variable. WhenA
calls any method ofB
, it gets lock on this/instance member...right? Means gets lock on instance ofB
itself or its member... can u just explain the difference? -
Gopi over 13 yearsoh.. sorry for misunderstanding your question. So for that, the answer would be same as what Jon Skeet has answered.
-
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 over 13 yearsyah, so i it needs to make sync method, it shuold use private member object instead of 'this' ... right? ok...
-
Maheshwar Ligade about 8 yearssynchronised(new Object ) vs synchronised(this ) what is the actual difference between this two, when to use which one
-
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 againstthis
as you know that only your code has access to that monitor to synchronize on it. -
try-catch-finally over 6 yearsIt does not answer the question (use
synchronized
orLocks
), no real explanation, broken link (archived version). Downvoted.