40

I am really new to Java and I read that synchronized is "very expensive" in Java. All I want to know is what is expensive and how is it expensive?

Thanks.

Hearen
  • 7,420
  • 4
  • 53
  • 63
unj2
  • 52,135
  • 87
  • 247
  • 375

5 Answers5

43

Maybe it's not as bad as you think

It used to be terrible (which is possibly why you read that it was "very expensive"). These memes can take a long time to die out

How expensive is synchronization?

Because of the rules involving cache flushing and invalidation, a synchronized block in the Java language is generally more expensive than the critical section facilities offered by many platforms, which are usually implemented with an atomic "test and set bit" machine instruction. Even when a program contains only a single thread running on a single processor, a synchronized method call is still slower than an un-synchronized method call. If the synchronization actually requires contending for the lock, the performance penalty is substantially greater, as there will be several thread switches and system calls required.

Fortunately, continuous improvements in the JVM have both improved overall Java program performance and reduced the relative cost of synchronization with each release, and future improvements are anticipated. Further, the performance costs of synchronization are often overstated. One well-known source has cited that a synchronized method call is as much as 50 times slower than an un-synchronized method call. While this statement may be true, it is also quite misleading and has led many developers to avoid synchronizing even in cases where it is needed.

Having said that - concurrent programming can still be slow, but not so much of it is purely Java's fault now. There is a trade-off between fine and coarse locking. Too coarse is obviously bad, but it's possible to be too fine too, as locks have a non zero cost.

It's important to consider the particular resource under contention. Mechanical hard disks are an example where more threads can lead to worse performance.

nircraft
  • 8,242
  • 5
  • 30
  • 46
John La Rooy
  • 295,403
  • 53
  • 369
  • 502
  • Is there a newer article now? Looks like Java 1.4 was not released at the time of this article. Since this post is on Google's top three for synchronisation performance, people might get the wrong idea reading this old article. Thanks. – Teddy Jul 16 '15 at 06:20
  • @Teddy, this question and answer are really about what synchronization was particularly slow in old versions of java. Now the problems with concurrent performance are just the same as every other language. Threads simply aren't the magic bullet some people wish them to be. – John La Rooy Jul 16 '15 at 07:01
15

It is expensive because if you are using threads, and a number of threads have to go through a synchronized section of code, only one of them may be executed at a time.

It is like a bottleneck.

It is even expensive when you use a single thread, because it has to check anyway if he is allowed to run.

If you reduce the use of synchronized segments your thread won't have to stop to see if they can run ( of course, they don't have to share data )

A high level overview of how synchronization works may be found here

http://img20.imageshack.us/img20/2066/monitor28synchronizatioc.png

A Java style monitor

OscarRyz
  • 196,001
  • 113
  • 385
  • 569
  • Yes the more contentious the lock, the more waiting/blocking for each contender, but I also suspect that suspending each thread that has to wait is expensive more than anything. – Alexander Mills Feb 10 '19 at 22:33
9

This isn't that specific to Java. Synchronization can be considered "expensive" in any multi-threaded environment if not done correctly. Whether it's particularly bad in Java, I do not know.

It prevents threads from running concurrently if they use the same resource. But, since they do use the same resource, there's no better option (it has to be done).

The problem is that people often protect a resource with too big a scope. For example, a badly designed program may synchronize an entire array of objects rather than each individual element in the array (or even a section of the array).

This would mean that a thread trying to read element 7 must wait for a thread reading or writing element 22. Not necessary. If the granularity of the synchronization were at the element level instead of the array level, those two threads wouldn't interfere with each other.

Only when two threads tried to access the same element would there be resource contention. That's why the general rule is to only protect as small a resource as possible (subject to limitations on number of synchronizations, of course).

But, to be honest, it doesn't matter how expensive it is if the alternative is data corruption due to two threads fighting over a single resource. Write your application correctly and only worry about performance problems if and when they appear ("Get it working first then get it working fast" is a favorite mantra of mine).

paxdiablo
  • 854,327
  • 234
  • 1,573
  • 1,953
5

This article over at IBM actually summarizes very nicely the main points behind synchronization.

Because of the rules involving cache flushing and invalidation, a synchronized block in the Java language is generally more expensive than the critical section facilities offered by many platforms, which are usually implemented with an atomic "test and set bit" machine instruction. Even when a program contains only a single thread running on a single processor, a synchronized method call is still slower than an unsynchronized method call. If the synchronization actually requires contending for the lock, the performance penalty is substantially greater, as there will be several thread switches and system calls required.

Vincent Ramdhanie
  • 102,349
  • 23
  • 137
  • 192
  • 17
    Please be aware that the newest Java version that article quotes is Java 1.3. That version was released in May 2000 and has long since been EOLed. While the basic facts remain somewhat similar (the Java Memory Model changed some of it), there have been tons of optimizations that make synchronization very cheap in the unontested case for example. – Joachim Sauer Nov 04 '09 at 01:06
  • s/unontested/uncontested/ obviously. – Joachim Sauer Nov 04 '09 at 01:14
  • 3
    And, of course, both mutual-exclusion of code blocks, and coherency of memory are fundamentally necessary when writing multithreaded code, and there are no "clever" tricks (only subtly broken ones) in Java to avoid them. If your two threads have to interact, you have to synchronize - pure and simple. Granularity synchronization is the only question remaining. – Lawrence Dol Nov 04 '09 at 01:18
3

The other answers give a good level of technical detail that I'm not going to attempt to replicate.

What I will do is advise you to check the dates of the articles (as well as the implied competence and awareness of the author). Synchronization in Java was very slow in earlier JVMs. However, it's improved a lot recently, such that uncontended synchronization is a lot faster than you might think, and uncontended synchronization has improved too.

Mind you, this question possibly doesn't matter - if you need to synchronize to ensure correctness, you need to synchronize to ensure correctness. The only times I can see the speed being an issue is if you were considering creating a lockless implementation instead (using the very efficient yet complex java.util.concurrent.locks.AbstractQueuedSynchronizer), or perhaps considering using another language for your task instead.

In general I think the best conclusion is that synchronization is generally fast enough to use on a first iteration. As with all performance concerns, code for clarity and correctness at first and then only optimise what you measure to be an expensive part of your application. Typically, this won't be the cost of synchronization*.

Andrzej Doyle
  • 102,507
  • 33
  • 189
  • 228