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
?)
You'll want to synchronize on an object that can serve as a Mutex. If the current instance (the this reference) is suitable (not a Singleton, for instance), you may use it, as in Java any Object may serve as the Mutex.
In other occasions, you may want to share a Mutex between several classes, if instances of these classes may all need access to the same resources.
It depends a lot on the environment you're working in and the type of system you're building. In most Java EE applications I've seen, there's actually no real need for synchronization...
As earlier answerers have noted, it is best practice to synchronize on an object of limited scope (in other words, pick the most restrictive scope you can get away with, and use that.) In particular, synchronizing on
this
is a bad idea, unless you intend to allow the users of your class to gain the lock.A particularly ugly case arises, though, if you choose to synchronize on a
java.lang.String
. Strings can be (and in practice almost always are) interned. That means that each string of equal content - in the ENTIRE JVM - turns out to be the same string behind the scenes. That means that if you synchronize on any String, another (completely disparate) code section that also locks on a String with the same content, will actually lock your code as well.I was once troubleshooting a deadlock in a production system and (very painfully) tracked the deadlock to two completely disparate open source packages that each synchronized on an instance of String whose contents were both
"LOCK"
.Just to highlight that there are also ReadWriteLocks available in Java, found as java.util.concurrent.locks.ReadWriteLock.
In most of my usage, I seperate my locking as 'for reading' and 'for updates'. If you simply use a synchronized keyword, all reads to the same method/code block will be 'queued'. Only one thread can access the block at one time.
In most cases, you never have to worry about concurrency issues if you are simply doing reading. It is when you are doing writing that you worry about concurrent updates (resulting in lost of data), or reading during a write (partial updates), that you have to worry about.
Therefore a read/write lock makes more sense to me during multi-threaded programming.
I try to avoid synchronizing on
this
because that would allow everybody from the outside who had a reference to that object to block my synchronization. Instead, I create a local synchronization object:Now I can use that object for synchronization without fear of anybody “stealing” the lock.
This declaration synchronizes entire method.
This declaration synchronized a part of code block instead of entire method.
From oracle documentation page
making these methods synchronized has two effects:
First, it is not possible for two invocations of synchronized methods on the same object to interleave. When one thread is executing a synchronized method for an object, all other threads that invoke synchronized methods for the same object block (suspend execution) until the first thread is done with the object.
There are many possibilities and alternatives to synchronization. You can make your code thread safe by using high level concurrency APIs( available since JDK 1.5 release)
Refer to below SE questions for more details:
Synchronization vs Lock
Avoid synchronized(this) in Java?
Personally, I think the answers which insist that it is never or only rarely correct to sync on
this
are misguided. I think it depends on your API. If your class is a threadsafe implementation and you so document it, then you should usethis
. If the synchronization is not to make each instance of the class as a whole threadsafe in the invocation of it's public methods, then you should use a private internal object. Reusable library components often fall into the former category - you must think carefully before you disallow the user to wrap your API in external synchronization.In the former case, using
this
allows multiple methods to be invoked in an atomic manner. One example is PrintWriter, where you may want to output multiple lines (say a stack trace to the console/logger) and guarantee they appear together - in this case the fact that it hides the sync object internally is a real pain. Another such example are the synchronized collection wrappers - there you must synchronize on the collection object itself in order to iterate; since iteration consists of multiple method invocations you cannot protect it totally internally.In the latter case, I use a plain object:
However, having seen many JVM dumps and stack traces that say a lock is "an instance of java.lang.Object()" I have to say that using an inner class might often be more helpful, as others have suggested.
Anyway, that's my two bits worth.
Edit: One other thing, when synchronizing on
this
I prefer to sync the methods, and keep the methods very granular. I think it's clearer and more concise.