Reputation: 8933
I was wondering if there is a situation where this statement will be true and needed. All the examples I have seen only synchronize on the "this" reference. Can someone tell me how a block of code in one object can be synchronized on any other reference apart from this ?
Upvotes: 0
Views: 2032
Reputation: 328737
Yes the statement is true.
There are several reasons why one would want NOT to use an intrinsic monitor (synchronized(this)
) - one of these reasons is that it can create liveness issues - in the code below, B uses an instance of A as a lock, maybe to control access to that variable. If another thread uses that same instance of A and tries to run a.methodA()
, it will be blocked until methodB()
is over.
So using an intrinsic monitor exposes the synchronization policy and can lead to subtle bugs and performance issues.
public class A {
public synchronized void methodA() {}
}
public class B {
A a = new A();
public void methodB() {
synchronized(a) {
// do something a little long
}
}
public A getA() {return a;}
}
If A had used an internal monitor that problem would not be possible.
public class A {
private final Object lock = new Object();
public void methodA() {
synchronized(lock) {}
}
}
Another scenario where using ad hoc monitors makes sense is when a class contains 2 (or more) unrelated objects, that both need to be accessed in a synchronized manner. Using 2 monitors instead of one reduces contention as the 2 objects can now be accessed concurrently.
Upvotes: 1
Reputation: 29646
In Java, you can use synchronized
constructs to create instrinsic locks on any object reference, yes. Read the relevant Java Tutorial.
The immediate example of not using synchronized
with this is when synchronizing on the Class
object, which is how static synchronized
methods work. In reality, there are plenty of valid uses. You may want to avoid using synchronized (this)
in favor of an internal implementation lock as otherwise you are setting a restriction that you use the lock internally, which other code you're not aware of might violate.
You should know, however, that often times you can replace synchronized
usage with a ReentrantLock
. You can read more about this in my post here.
Upvotes: 0
Reputation: 1012
Yes it can be done.
The synchronize block will use that object as a lock, rather than the whole class. People that use synchronized(this) { } put an exclusive lock on the whole object, which might be what you want. However, you might have something like a persister, which is the only thing that needs to be synchronized. synchronized(persister) { }, would provide a less granular way of doing this.
Upvotes: 0
Reputation: 2675
public class SyncTest{
private Object obj = new Object();
public void func1() {
synchronized(obj) {
obj.something();
}
}
Upvotes: 0