In Java critical sections, what should I synchroni

2019-01-04 17:02发布

In Java, the idiomatic way to declare critical sections in the code is the following:

private void doSomething() {
  // thread-safe code
  synchronized(this) {
    // thread-unsafe code
  }
  // thread-safe code
}

Almost all blocks synchronize on this, but is there a particular reason for this? Are there other possibilities? Are there any best practices on what object to synchronize on? (such as private instances of Object?)

9条回答
The star\"
2楼-- · 2019-01-04 18:04

First, note that the following code snippets are identical.

public void foo() {
    synchronized (this) {
        // do something thread-safe
    }
}

and:

public synchronized void foo() {
    // do something thread-safe
}

do exactly the same thing. No preference for either one of them except for code readability and style.

When you do synchronize methods or blocks of code, it's important to know why you are doing such a thing, and what object exactly you are locking, and for what purpose.

Also note that there are situations in which you will want to client-side synchronize blocks of code in which the monitor you are asking for (i.e. the synchronized object) is not necessarily this, like in this example :

Vector v = getSomeGlobalVector();
synchronized (v) {
    // some thread-safe operation on the vector
}

I suggest you get more knowledge about concurrent programming, it will serve you a great deal once you know exactly what's happening behind the scenes. You should check out Concurrent Programming in Java, a great book on the subject. If you want a quick dive-in to the subject, check out Java Concurrency @ Sun

查看更多
爷、活的狠高调
3楼-- · 2019-01-04 18:05

On what you synchronize depends on what other threads that might potentially get into conflict with this method call can synchronize.

If this is an object that is used by only one thread and we are accessing a mutable object which is shared between threads, a good candidate is to synchronize over that object - synchronizing on this has no point since another thread that modifies that shared object might not even know this, but does know that object.

On the other hand synchronizing over this makes sense if many threads call methods of this object at the same time, for instance if we are in a singleton.

Note that a syncronized method is often not the best option, since we hold a lock the whole time the method runs. If it contains timeconsuming but thread safe parts, and a not so time consuming thread-unsafe part, synchronizing over the method is very wrong.

查看更多
闹够了就滚
4楼-- · 2019-01-04 18:06

Synchronization in Java often involves synchronizing operations on the same instance. Synchronizing on this then is very idiomatic since this is a shared reference that is automatically available between different instance methods (or sections of) in a class.

Using another reference specifically for locking, by declaring and initializing a private field Object lock = new Object() for example, is something I never needed or used. I think it is only useful when you need external synchronization on two or more unsynchronized resources inside an object, although I would always try to refactor such a situation into a simpler form.

Anyway, implicit (synchronized method) or explicit synchronized(this) is used a lot, also in the Java libraries. It is a good idiom and, if applicable, should always be your first choice.

查看更多
登录 后发表回答