aspose file tools*
The moose likes Threads and Synchronization and the fly likes does synchronization expensive Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login
JavaRanch » Java Forums » Java » Threads and Synchronization
Bookmark "does synchronization expensive" Watch "does synchronization expensive" New topic
Author

does synchronization expensive

sam liyanage
Ranch Hand

Joined: Nov 25, 2008
Posts: 1032
i read that synchronization is expensive when i reading singleton pattern.how it is expensive when use synchronization ?
Rob Spoor
Sheriff

Joined: Oct 27, 2005
Posts: 19543
    
  16

Moving to Threads / Synchronization.


SCJP 1.4 - SCJP 6 - SCWCD 5 - OCEEJBD 6
How To Ask Questions How To Answer Questions
Steve Luke
Bartender

Joined: Jan 28, 2003
Posts: 3949
    
  17

Nowadays Synchronization itself is not expensive, at least not enough to worry about. Early on in Java just getting a lock to synchronize on took some time, but that has been optimized in later implementations (Java 1.4 and later I believe).

The cost now of Synchronization is the cost when a lock is contested - that is, if Thread-1 tries to get a lock that Thread-2 already has then Thread-1 has to wait for Thread-2 to release it. So there has been work done recently to reduce the need to exclusively lock other Threads from blocks of code. Things like a fixed volatile functionality, concurrent collection implementations inside the java.util.concurrent package, and more flexible locks inside the java.util.concurrent.lock package.


Steve
G.Sathish kumar
Ranch Hand

Joined: Jul 27, 2009
Posts: 84
Steve Luke wrote:Nowadays Synchronization itself is not expensive, at least not enough to worry about. Early on in Java just getting a lock to synchronize on took some time, but that has been optimized in later implementations (Java 1.4 and later I believe).

The cost now of Synchronization is the cost when a lock is contested - that is, if Thread-1 tries to get a lock that Thread-2 already has then Thread-1 has to wait for Thread-2 to release it. So there has been work done recently to reduce the need to exclusively lock other Threads from blocks of code. Things like a fixed volatile functionality, concurrent collection implementations inside the java.util.concurrent package, and more flexible locks inside the java.util.concurrent.lock package.


i feel synchronization is not expensive but it should be time consuming process when more threads access the same resource. please correct me if i am wrong


Thanks
Sathish kumar
SCJP, SCWCD
Steve Luke
Bartender

Joined: Jan 28, 2003
Posts: 3949
    
  17

G.Sathish kumar wrote:
Steve Luke wrote:Nowadays Synchronization itself is not expensive, at least not enough to worry about. Early on in Java just getting a lock to synchronize on took some time, but that has been optimized in later implementations (Java 1.4 and later I believe).

The cost now of Synchronization is the cost when a lock is contested - that is, if Thread-1 tries to get a lock that Thread-2 already has then Thread-1 has to wait for Thread-2 to release it. So there has been work done recently to reduce the need to exclusively lock other Threads from blocks of code. Things like a fixed volatile functionality, concurrent collection implementations inside the java.util.concurrent package, and more flexible locks inside the java.util.concurrent.lock package.


i feel synchronization is not expensive but it should be time consuming process when more threads access the same resource. please correct me if i am wrong


Yes, that is correct. And the expense mainly comes because any second/third/etc... threads that try to access the synchronized block must wait (and therefore do nothing) until the first one is finished.

This is why it is best to keep synchronized blocks as short as possible, and whenever you can look into structures which will help you avoid using them but still get thread safe data.
luri ron
Ranch Hand

Joined: Dec 11, 2008
Posts: 86
synchronization is certainly expensive. it takes a dozen of instructions each you get a lock before you execute your block. cas (compare and set) from the jdk 1.5 concurrent package which is atomic, and it takes half of the instructions required for a lock.

also, synchronization doesn't give the program any flexibility for different lock policy. for example, a reader lock should not exclude another reader.

for concurrent programing, if you can avoid synchronize, i would sugget you do it.
Mike Simmons
Ranch Hand

Joined: Mar 05, 2008
Posts: 2969
    
    9
Saying "X is expensive" is pretty much meaningless unless we have some point of comparison. Expensive compared to what? And more importantly, how often is the potentially "expensive" operation actually invoked? Without some sort of qualifiers, saying something is "certainly expensive" seems quite foolhardy.

Frankly, the number of times that counting bytecode instructions is a useful measure of anything... is remarkably small, in my experience. I don't doubt that some situations exist in which synchronization can be significantly slower than other techniques. And for a few of these situations, this might even be observable by customers in some way. But there are also many more situations where such differences are not significant. So I cannot agree with the advice here, in general - it actually applies to a much smaller set of circumstances than the author claims.

I would also add that there's been a huge amount of badly-written, buggy code created by people trying, often for no good reason, to avoid synchronization, because someone told them it was "slow" or "expensive". Now, since JDK 1.5, good alternate techniques are much more available than they were before. And that's great. But these techniques have their own learning curves. Often, synchronization remains the simplest solution that actually results in thread-safe code. It can still be error-prone, true - thats an ongoing problem for all concurrent Java code, including code that uses the 1.5 concurrency libraries. But I think it's a bad idea to spread the idea that synchronization is something to be avoided in general. Especially if that idea is based on performance considerations, without measuring actual performance for your specific situation.
luri ron
Ranch Hand

Joined: Dec 11, 2008
Posts: 86
you can compare HashTable and ConcurrentHashMap for performance. HashTable synchronize each method, but ConcurrentHashMap use read/write lock and cas. I suggest you don't use HashTable if you don't have to, but it is just my suggestion...

i agree with your good programmer point. but sometimes it can be a tough sale to management as time to market and improving the bottomeline takes priority for ppl with a MBA degree :-)
Monu Tripathi
Rancher

Joined: Oct 12, 2008
Posts: 1369

You may want to read this: Urban Performance Legends - Brian Goetz


[List of FAQs] | [Android FAQ] | [Samuh Varta]
luri ron
Ranch Hand

Joined: Dec 11, 2008
Posts: 86
thanks very good library of java stuff.
if you take a look at this article it tells a lot about the cas for nonblocking algorithm.
cas

i also put together a quick java program so you swap in Hashtable or ConcurrentHashMap to see the difference. it is about 10-20% performance improvement using ConcurrentHashMap in this simple program. i also stress the importance of having read/write lock by having multiple get with one put.

Steve Luke
Bartender

Joined: Jan 28, 2003
Posts: 3949
    
  17

Hi luri,

I guess we are straying a bit from what the original question was. You can't really compare the speeds of different collections and suggest that is due to synchronization or not. There are a LOT of difference between a Hashtable and a ConcurrentHashMap. You show very clearly that the newer concurrent collections are more efficient than the older synchronized ones, and so it is a good idea to use the newer collections vs. the older whens when concurrency is required. That does not reflect on the speed of synchronization as a whole, though.

Consider the below code (sorry, it is a bit more complex, mainly because it is mirrored off of some strategies I use in real-word stuff). The base comparison is between 3 methods in the SynchronizedSpeed class. The unsynchronizedCalls method calls the compoundInterest method without any synchronization, synchronizedBlocks calls the method surrounded by a synchronized block, and concurrentlyLock calls it surrounded by a ReentrantLock. The rest has to do with controlling the threading behavior and controlling which methods get called.

Application should be run like:

nLoops: Number of total interest calculation loops to run
nThreads: Number of threads to execute those loops in

The number of loops should be evenly divisible by the number of threads or incor
rect values will be calculated.

To see the relative 'cost' of synchronization run the code with a single thread (put a lot of loops, but not more than 70,000 since we reach infinity then). You won't see contested operations or incorrect calculations so the only time difference should be the overhead involved in the synchronization. See anything surprising? Now run the application with a few more threads (number of processors on the computer, 20, 100). Then run the application with a lot of threads (1000+).

SynchronizedSpeed class


InterestCalculator class does the work for each loop


InterestCalculation enum is a simple enum for controlling which methods get called for any particular run.


My results:


More tests? Run the code with the code inside the compoundInterest method commented out to see the results of the false comparisons Brian Goetz is talking about in the article.
luri ron
Ranch Hand

Joined: Dec 11, 2008
Posts: 86
can you send me the snippet about false comparison?

here is the snippet from the link i sent in my previous message, and it best summarize it. and this is by brian goetz.

Under light to moderate contention, nonblocking algorithms tend to outperform blocking ones because most of the time the CAS succeeds on the first try, and the penalty for contention when it does occur does not involve thread suspension and context switching, just a few more iterations of the loop. An uncontended CAS is less expensive than an uncontended lock acquisition (this statement has to be true because an uncontended lock acquisition involves a CAS plus additional processing), and a contended CAS involves a shorter delay than a contended lock acquisition.

Under high contention -- when many threads are pounding on a single memory location -- lock-based algorithms start to offer better throughput than nonblocking ones because when a thread blocks, it stops pounding and patiently waits its turn, avoiding further contention. However, contention levels this high are uncommon, as most of the time threads interleave thread-local computation with operations that contend for shared data, giving other threads a chance at the shared data. (Contention levels this high also indicate that reexamining your algorithm with an eye towards less shared data is in order.) The graph in "Going atomic" was somewhat confusing in this regard, as the program being measured was so unrealistically contention-intensive that it appeared that locks were a win for even small numbers of threads
Steve Luke
Bartender

Joined: Jan 28, 2003
Posts: 3949
    
  17

This is the quote from the 'Urban Legends' link Monu posted above. Basically the entire synchronization section talks about it. Pulling out the important parts:

Urban performance legend #1: Synchronization is really slow
...
Even if it was once true, though, it certainly isn't anymore. JVMs have improved tremendously since JDK 1.0. Synchronization is implemented more efficiently, and the JVM is sometimes able to identify that a synchronization is not actually protecting any data and can be eliminated. But more significantly, the microbenchmark in Listing 1 is fundamentally flawed. First of all, microbenchmarks rarely measure what you think they're measuring. In the presence of dynamic compilation, you have no idea what bytecode the JVM decides to convert into native code or when, so you can't really compare apples to apples.

In addition, you have no idea what the compiler or JVM is optimizing away -- some Java compilers will completely optimize away calls to unsyncMethod, because it does nothing, and others may also optimize away syncMethod, or the synchronization on syncMethod, because it also does nothing. Which does your compiler optimize away, and under what circumstances? You don't know, but it almost certainly distorts the measurements.

Regardless of the actual numbers, concluding that unsynchronized method calls are X times faster than synchronized ones from a benchmark of this type is just plain foolish. Synchronization is likely to add a constant overhead to a block of code, not slow it down by a constant factor. How much code is in the block will dramatically affect the "ratio" computed by Listing 1. The synchronization overhead as a percentage of the time to execute an empty method is a meaningless number.

Once you start comparing the runtime of real synchronized methods to their unsynchronized counterparts on modern JVMs, you'll find that the overhead is nothing near the alarmist "50 times" that is so often bandied about. Read Part 1 of the series Threading lightly, "Synchronization is not the enemy" (see Resources), for some rough and unscientific measurements of the overhead of synchronization. To be sure, there is some overhead to uncontended synchronization (and much more for contended synchronization), but synchronization is not the sewer-dwelling, performance-eating alligator that so many fear.


And, if you run my code (or I should say, at least when I run my sample code) with a single thread (the results are listed in my previous post) I get speed increase when I put synchronized blocks in there (reproduceably 2x faster than unsynchronized or java.util.concurrent.locked). This is rather confusing to me, but my guess is there is some heavy duty optimizations going on there that I can't predict. This is exactly the point Brian is making - it is hard to predict but synchronization by itself will not kill a real application's performance. Further, he mentions the 'false microbenchmark' of comparing no-op code. If you comment out the code I mention in my snippet you will see that very same effect. Essentially, if the code does nothing, then the benchmark is meaningless. If it does something, then the benchmark means something in that context. In your real-world context the effect will be different still.

As I said, this is a very different discussion that the use of non-blocking collections and data structures. The non-blocking structures are used to reduce the contention between threads so no thread has to wait to act - it is continuously acting even if it has to repeat a couple of times to get the job done. I agree that you should use them when practical. The question of 'is synchronization expensive' is a different story altogether. Synchronization is not very expensive, and should not be avoided for the 'performance' consideration of synchronization alone. What you use to benchmark the task will have more effect on the benchmark than what you are actually trying to measure (as per +/- real code executed each loop, how many loops, how many threads, high CPU use or I/O use, etc...). Synchronized lock contention may be expensive and if you have highly contested regions of code then looking for alternate schemes is a good thing - there are options often available with constructive use of the java.util.concurrent packages as the link you provide indicates. Noone is saying you shouldn't use them.

But answering the question 'Is synchronization expensive?' with an answer of 'Yes, use alternate methods.' is misleading and can lead to design compromises. As Mike said previously the only way to know if synchronized blocks are slow in your situation is to test and measure performance. Then compare it to alternative, equally safe methods and see which performs better.
Henry Wong
author
Sheriff

Joined: Sep 28, 2004
Posts: 18117
    
  39

luri ron wrote:can you send me the snippet about false comparison?

here is the snippet from the link i sent in my previous message, and it best summarize it. and this is by brian goetz.

[Paragraphs deleted only for brevity -- I agree with the paragraphs (and there is nothing wrong with it)]



One thing to remember is that optimistic locking is not for the faint of heart. Just as using threads is much harder than not using threads -- meaning many developers seems to just not "get it". Optimistic algorthms is also a jump in complexity.

While a CAS is a simple idea, understanding the issues in using it -- maintaining atomicy, race conditions, recovery from collisions -- can be difficult. If you are just starting out learning threads, it may be a good idea to wait til you get more comfortable using threads first.

Henry


Books: Java Threads, 3rd Edition, Jini in a Nutshell, and Java Gems (contributor)
luri ron
Ranch Hand

Joined: Dec 11, 2008
Posts: 86
ok steve, i will change my statement to be synchronization is more expensive than cas/concurrent implementation.
Steve Luke
Bartender

Joined: Jan 28, 2003
Posts: 3949
    
  17

I tried to come up with a method to use the CAS alternative for the above code, just so I could get another comparison. The code below was inserted with some glue which I am skipping:

Modifications to InterestCalculator to provide an Atomic version of the principal. This is where the real CAS operation is. Please let me know if the operation is inefficient - it was the only one I came up with that appeared to be safe.


The SynchronizeSpeed class was modified a bit to make use of it:


And the enum was updated as well:


Anyway, speeds for CAS where between the speeds of using synchronized blocks and ReentrantLocks. With 1 thread, is was a tad slower than synchronized blocks but faster than non-synched blocks and locks. Under medium contention it was pretty much equal to everything else, and under high contention it was faster than synchronized blocks but slower than Locks. I bring this up because the theory behind CAS might make it seem faster, but in practice there appears to be many more hoops to jump through which tempers the possible benefits. I threw together a graph.

The lines are an exponential regression of 3 repeats for each thread count. The plot should really be bi-phasic with an initial exponential-like drop between the first 2 data points, but my graphing app didn't have the proper algorithm.



[Thumbnail for Speed of Various Synch Methods.jpg]

luri ron
Ranch Hand

Joined: Dec 11, 2008
Posts: 86
thanks for sharing your test program. however, there are a few i want to point out in your program.
1. i would not run all the locking in one jvm run. maybe adding another input argument to tell which locking logic to use for each run. this way you can eliminate the side effect introduced such as gc.
2. ReentrantLock doesn't offer much difference from Synchronize. so it is misleading to use it in your concurrentlyLock method.
3. here is how i would make modification to your program to leverage cas using AtomicInteger. the change will be only in SynchronizedSpeed.java.




4. if you test my implementation with 2 - 3 threads, you will see a big improvement using cas instead of synchronize. P.S., using System.nanoTime for your time measurement. However, your program is high contention in nature as all the thread does is to get a lock and then calculate the account data, then release it. So when you start to increase the number of threads, the benefit of cas diminish. In a pratical multithread app, you would implement your threads that lead to moderate/small contention.
Steve Luke
Bartender

Joined: Jan 28, 2003
Posts: 3949
    
  17

Thanks luri,

Using the CAS approach as a locking mechanism makes a lot of sense, rather than building it into the data model. Thanks, I will have to try that.

As for the other points, my original tests actually did use a different JVM run to test the different locking mechanisms (which is why I used the enum, I had a command line argument that I could just do InterestCalculation.valueOf(arg[2]) to choose which calculation to run.) But the output was harder to copy/paste so I rolled them all into the same application - there were no differences I saw between the two situations.

I also included the ReentrantLock just to add that as a comparison - not because it had much to do with the CAS vs. Synchronized approach but more to see if there was any gain/loss compared with the synchronized blocks.

I will want to run the CAS approach you defined to my test suite, when I do I will let you know the results. I do think (and this is the point I tried to make before, and that I think Brian Goetz was making) was that all these benchmarks are very situation specific. The ubiquitous 'Your Mileage May Vary' should be applied.
 
wood burning stoves
 
subject: does synchronization expensive
 
Similar Threads
Synchronization
Synchronized
how will i improve performance when i use synchronization
What is the real deal with the use of synchronized
WA #1.....word association