简体   繁体   中英

In Java, synchronized block can synchronize on any object reference?

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 ?

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.

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 .

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.

public class SyncTest{
    private Object obj = new Object();

    public void func1() {
        synchronized(obj) {
            obj.something();
        }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM