Question:
I am interested in keeping my code running as fast as possible. Is there a cost associated with making my methods synchronized, and if so, how significant a cost?
Answer:
There is a time penalty associated with executing synchronizedmethods and blocks. The value of this penalty varies depending on thevirtual machine, the underlying operating system, the threadimplementation, and other factors. When you execute a synchronizedmethod or block, the JVM checks if the calling thread owns the monitorassociated with synchronized code. If so, the JVM increments acounter associated with the monitor to account for recursive lockacquisition and execution continues normally until the end of thesynchronized code is reached, whereupon the JVM decrements the lockcounter. If the counter equals zero, the JVM releases the thread’sownership of the monitor. If the calling thread did not already ownthe monitor, the JVM checks to see if any other thread already ownsthe monitor. If so, the calling thread is blocked until the monitoris released and another attempt to acquire it can be made. If not,the JVM assigns ownership of the monitor to the thread and incrementsthe lock counter.
All of the aforementioned tasks consume CPU cycles that would notnormally be executed in unsynchronized code. A JVM or JIT, such asHotSpot, can perform various optimizations to reduce the cost of thesetasks. But there will always be a cost. The only way to assess theimpact on the performance of your code is to time the code in yourprojected production environment. You can also take steps to makesure you are not unnecessarily using synchronization. Blindlysynchronizing all the methods of a class is often not necessary. Twomethods may access completely different data structures and notrequire mutual exclusion. In such a case, you would eschew declaringthe methods as synchronized. Instead, you would create separate lockvariables for use in synchronized blocks in each method.
It is possible to squeeze better performance out of threaded programs byonly synchronizing those code blocks that require protection.Unfortunately, performance is also very sensitive to the JVM.Traditionally, the high-overhead implementations of synchronization inJVMs has discouraged fine-grained synchronization. This encouragedthe synchronization of large code blocks. In an optimized runtimelike HotSpot, fine-grained synchronization is more efficient, causingold code with coarse-grained locks to unnecessarily block threads forlong periods of time. In the end, the rule with multithreaded code isthat you’ve got to measure your actual performance against yourrequirements and tweak accordingly.