java.net: Wiki

The Source for Java Technology Collaboration


 <<O>>  Difference Topic SynchronizationIsSlowMisconception (7 - 27 Aug 2003 - Main.redwolf)
Line: 1 to 1
 
META TOPICPARENT name="Misconceptions"
Home | Help | Changes | Index | Search | Go
Line: 10 to 10
 It has been repeated that synchronization is slow many times to the point that many people will go to great lengths to avoid synchronization without a full understanding of what they are avoiding. Synchronization is not free, there is a cost associated with it, but modern JVMs make it very cheap. What is expensive is contention.

What is Contention

Changed:
<
<
Contention happens when two threads compete for one resource, in Java that resource is an instance of an Object. When one thread has acquired a lock on an object and is still holding on to it, contention happens when another thread also tries to acquire a lock on the same object. The second thread is blocked until the first thread had released it's lock. This allows the second thread to acquire a lock and move forward.
>
>
Contention happens when two threads compete for one resource, in Java that resource is an instance of an Object. When one thread has acquired a lock on an object and is still holding on to it, contention happens when another thread also tries to acquire a lock on the same object. The second thread is blocked until the first thread has released it's lock. This allows the second thread to acquire a lock and move forward.
 

What is the cost of Synchronization without Contention

No matter what, when a Thread enters a synchronized block it must test for and acquire a lock. In newer JVMs (1.4.0) this cost is very small. So small that the slight implementation differences in java.util.Vector.set(int,Object) and java.util.ArrayList.set(int,Object) make the Vector faster in the 1.4.0-sever mode despite the fact that Vector's set method is synchronized and ArrayList's set method is not. See Java Performance Tuning page 291 for more info.
Line: 19 to 19
 The overwhelming cost of contention is the time spent idle waiting to acquire a lock. During this time a thread cannot move forward and continue to do work. This means that the cost of synchronization with contention includes the work done by any threads that acquire the lock on an object before this thread can continue. For any non-trivial application, the amount of work done in normal program flow completely dwarfs the work needed to acquire synchronization locks by orders of magnitude?.

The Solutions

Changed:
<
<
You cannot avoid synchronization when it's needed. If the algorithm you've chosen to implement requires synchronization for correct behavior, then you must use synchronization; otherwise you allow for possibly very subtle bugs. You can change your algorithm to one that does not require synchronization but this should be avoided unless it is understood that the possible algorithmic optimizations you are giving up are not significant. I personally consider blind avoidance of synchronization to be the same evil as premature optimization.
>
>
You cannot avoid synchronization when it's needed. If the algorithm you've chosen to implement requires synchronization for correct behavior, then you must use synchronization; otherwise you possibly allow for very subtle bugs. You can change your algorithm to one that does not require synchronization but this should be avoided unless it is understood that the possible algorithmic optimizations you are giving up are not significant. I personally consider blind avoidance of synchronization to be the same evil as premature optimization.
 

Small Synchronized Blocks

Changed:
<
<
One very common synchronization advice is to make your synchronized blocks as small as possible. In other words, you are doing as little work as possible inside of a synchronized block of code. The rationale is that since the cost of contention is relativity so expensive, don't worry about other synchronization costs. Also, this method does not require a full understanding of your application's behavior. The downside to this method is that the repeated acquisition and release of synchronization locks may be more expensive than contention if contention is extremely rare or not possible, like a single threaded application.
>
>
One very common synchronization advice is to make your synchronized blocks as small as possible. In other words, you are doing as little work as possible inside of a synchronized block of code. The rationale is that since the cost of contention is relatively so expensive, don't worry about other synchronization costs. Also, this method does not require a full understanding of your application's behavior. The downside to this method is that the repeated acquisition and release of synchronization locks may be more expensive than contention if contention is extremely rare or not possible, like a single threaded application.
 

Immutable Objects

Changed:
<
<
An immutable object cannot change value once it's been created. The java.lang.String is the most common example of an immutable object. Since an immutable object cannot be modified it is safe to share these objects between threads without the use of synchronization. Depending on their use immutable objects have other performance implications with respect to the garbage collector? that you should be aware of.
>
>
An immutable object cannot change value once it's been created. The [[String java.lang.String] is the most common example of an immutable object. Since an immutable object cannot be modified it is safe to share these objects between threads without the use of synchronization. Depending on their use immutable objects have other performance implications with respect to the garbage collector? that you should be aware of.
 

ThreadLocal

The java.lang.ThreadLocal class provides a convenient way for an instance to have per-Thread data. This allows you to avoid the need for synchronization because data is not shared between threads, each thread has it's own set of data. I've found this to be very helpful for caching results, let me give an example.
Changed:
<
<
I once wrote a Java Servlet? that transformed XML into HTML. The result of first few steps were the exact same every time but the result of those steps was not thread safe. So, I used ThreadLocal so that each thread could have it's own set of cached data and didn't have to synchronize access to the Servlet. The benefit of not having to repeat a lot of work plus the ability to take advantage of all CPU?s gave a good performance boost at the cost of increased memory consumption.
>
>
I once wrote a Java Servlet? that transformed XML into HTML. The result of the first few steps were exact same every time but the result of those steps was not thread safe. So, I used ThreadLocal so that each thread could have it's own set of cached data and didn't have to synchronize access to the Servlet. The benefit of not having to repeat a lot of work plus the ability to take advantage of all CPU?s gave a good performance boost at the cost of increased memory consumption.
 

Understanding your Application

Changed:
<
<
The suggestion to create many small Synchronized blocks, instead of one large one is commonly made because larger sections of synchonized code mean more complexity and the waiting time for other threads can grow a quite fast. Opposite to those negative points for big sections lies the point that it still takes more then a little amount of time to acquire the synchonization locks, so more locks means longer waiting time. Making a number of private methods synchonized instead of only the method that calls them means that it always takes n-times the lock time.
>
>
The suggestion to create many small Synchronized blocks, instead of one large one is commonly made because larger sections of synchronized code mean more complexity and the waiting time for other threads can grow quite fast. Opposite to those negative points for big sections lies the point that it still takes more than a little amount of time to acquire the synchonization locks, so more locks means longer waiting time. Making a number of private methods synchronized instead of only the method that calls them means that it always takes n-times the lock time.
 The only way to choose the size of your synchonized blocks correctly is to understand your application.
Changed:
<
<
For example; If a cache uses a Hashtable? repeatedly to check, update or delete cache entries the code gets slowed down because a Hashtable? is synchonized on most of its methods.
>
>
For example; If a cache uses a Hashtable? repeatedly to check, update or delete cache entries the code gets slowed down because a Hashtable? is synchronized on most of its methods.
 Imagine a method on this cache where you first check the entry exists, then creates one using a put and at the end fetches it again to return to the user.
public Object fetch(String key) {

Line: 58 to 58
 

Summary

Changed:
<
<
The cost of syncronization is very small. The cost of contention can be large. If you compare the source of Vector.set(...) and ArrayList.set(...) you'll see that the overhead of syncronization is less that the cost of a private method call and an integer comparision in a boolean expression. Pick a faster algorithm and don't get hung up on if it needs to be synchronized for correctness. Do consider the implications of contention when picking an algorithm.
>
>
The cost of synchronization is very small. The cost of contention can be large. If you compare the source of Vector.set(...) and ArrayList.set(...) you'll see that the overhead of synchronization is less that the cost of a private method call and an integer comparison in a boolean expression. Pick a faster algorithm and don't get hung up on if it needs to be synchronized for correctness. Do consider the implications of contention when picking an algorithm.
 

References


 <<O>>  Difference Topic SynchronizationIsSlowMisconception (6 - 28 Jun 2003 - Main.zander)
Line: 1 to 1
 
META TOPICPARENT name="Misconceptions"
Home | Help | Changes | Index | Search | Go
Line: 33 to 33
 I once wrote a Java Servlet? that transformed XML into HTML. The result of first few steps were the exact same every time but the result of those steps was not thread safe. So, I used ThreadLocal so that each thread could have it's own set of cached data and didn't have to synchronize access to the Servlet. The benefit of not having to repeat a lot of work plus the ability to take advantage of all CPU?s gave a good performance boost at the cost of increased memory consumption.

Understanding your Application

Changed:
<
<
  • ALERT! This section is unclear and I, Sandy, am having trouble thinking of a good example that is short and easy to understand. If someone has a suggestion please step forward.
The Small Synchronized Blocks suggestion above is very common becase it's easy to implement and won't have large negative effects if implemented poorly. Each time the code crosses a synchronized boundary it must do the work to test for and acquire the lock. While this process is cheap, it is not free. If it is known that a shared resource is not likely to be contended for by many threads then it may be desireable to only synchronize once on that resource while doing work instead of many times on that resource while doing work.
>
>
The suggestion to create many small Synchronized blocks, instead of one large one is commonly made because larger sections of synchonized code mean more complexity and the waiting time for other threads can grow a quite fast. Opposite to those negative points for big sections lies the point that it still takes more then a little amount of time to acquire the synchonization locks, so more locks means longer waiting time. Making a number of private methods synchonized instead of only the method that calls them means that it always takes n-times the lock time.
The only way to choose the size of your synchonized blocks correctly is to understand your application.

For example; If a cache uses a Hashtable? repeatedly to check, update or delete cache entries the code gets slowed down because a Hashtable? is synchonized on most of its methods. Imagine a method on this cache where you first check the entry exists, then creates one using a put and at the end fetches it again to return to the user.

public Object fetch(String key) {
	 if(! myHashtable.containsKey(key)) {
		  myHashtable.put(key, createNewEntry(key));
	}
	 return myHashtable.get(key);
}

This would be faster if you would use a HashMap? (which is not synchonized) and synchonize your whole method:

public synchonized Object fetch(String key) {
	 if(! myHashMap.containsKey(key)) {
		  myHashMap.put(key, createNewEntry(key));
	}
	 return myHashMap.get(key);
}
 

Summary

The cost of syncronization is very small. The cost of contention can be large. If you compare the source of Vector.set(...) and ArrayList.set(...) you'll see that the overhead of syncronization is less that the cost of a private method call and an integer comparision in a boolean expression. Pick a faster algorithm and don't get hung up on if it needs to be synchronized for correctness. Do consider the implications of contention when picking an algorithm.
Line: 49 to 70
 

Discussion about SynchronizationIsSlowMisconception

Deleted:
<
<
I can't follow your example in "Understanding your Application" could you please explain it again? Maybe with an example? (TZ?)

 <<O>>  Difference Topic SynchronizationIsSlowMisconception (5 - 28 Jun 2003 - Main.leknor)
Line: 1 to 1
 
META TOPICPARENT name="Misconceptions"
Home | Help | Changes | Index | Search | Go
Line: 33 to 33
 I once wrote a Java Servlet? that transformed XML into HTML. The result of first few steps were the exact same every time but the result of those steps was not thread safe. So, I used ThreadLocal so that each thread could have it's own set of cached data and didn't have to synchronize access to the Servlet. The benefit of not having to repeat a lot of work plus the ability to take advantage of all CPU?s gave a good performance boost at the cost of increased memory consumption.

Understanding your Application

Added:
>
>
  • ALERT! This section is unclear and I, Sandy, am having trouble thinking of a good example that is short and easy to understand. If someone has a suggestion please step forward.
 The Small Synchronized Blocks suggestion above is very common becase it's easy to implement and won't have large negative effects if implemented poorly. Each time the code crosses a synchronized boundary it must do the work to test for and acquire the lock. While this process is cheap, it is not free. If it is known that a shared resource is not likely to be contended for by many threads then it may be desireable to only synchronize once on that resource while doing work instead of many times on that resource while doing work.

Summary


 <<O>>  Difference Topic SynchronizationIsSlowMisconception (4 - 23 Jun 2003 - Main.zander)
Line: 1 to 1
 
META TOPICPARENT name="Misconceptions"
Home | Help | Changes | Index | Search | Go
Line: 16 to 16
 No matter what, when a Thread enters a synchronized block it must test for and acquire a lock. In newer JVMs (1.4.0) this cost is very small. So small that the slight implementation differences in java.util.Vector.set(int,Object) and java.util.ArrayList.set(int,Object) make the Vector faster in the 1.4.0-sever mode despite the fact that Vector's set method is synchronized and ArrayList's set method is not. See Java Performance Tuning page 291for more info.

What is the cost of Synchronization with Contention

Changed:
<
<
The overwhelming cost of contention is the time spent idle waiting to acquire a lock. During this time a thread cannot move foreword and continue to do work. This means that the cost of synchronization with contention includes the work done by any threads that acquire the lock on an object before this thread can continue. For any non-trivial application, the amount of work done in normal program flow completely dwarfs the work needed to acquire synchronization locks by orders of magnitude?.
>
>
The overwhelming cost of contention is the time spent idle waiting to acquire a lock. During this time a thread cannot move forward and continue to do work. This means that the cost of synchronization with contention includes the work done by any threads that acquire the lock on an object before this thread can continue. For any non-trivial application, the amount of work done in normal program flow completely dwarfs the work needed to acquire synchronization locks by orders of magnitude?.
 

The Solutions

You cannot avoid synchronization when it's needed. If the algorithm you've chosen to implement requires synchronization for correct behavior, then you must use synchronization; otherwise you allow for possibly very subtle bugs. You can change your algorithm to one that does not require synchronization but this should be avoided unless it is understood that the possible algorithmic optimizations you are giving up are not significant. I personally consider blind avoidance of synchronization to be the same evil as premature optimization.
Line: 25 to 25
 One very common synchronization advice is to make your synchronized blocks as small as possible. In other words, you are doing as little work as possible inside of a synchronized block of code. The rationale is that since the cost of contention is relativity so expensive, don't worry about other synchronization costs. Also, this method does not require a full understanding of your application's behavior. The downside to this method is that the repeated acquisition and release of synchronization locks may be more expensive than contention if contention is extremely rare or not possible, like a single threaded application.

Immutable Objects

Changed:
<
<
An immutable object cannot change value once it's been created. The java.lang.String is the most common example of an immutable object. Since an immutable object cannot be modified it is safe to share these objects between threads without the use of synchronization. Depending on thier use immutable objects have other performance implications with respect to the garbage collector? that you should be aware of.
>
>
An immutable object cannot change value once it's been created. The java.lang.String is the most common example of an immutable object. Since an immutable object cannot be modified it is safe to share these objects between threads without the use of synchronization. Depending on their use immutable objects have other performance implications with respect to the garbage collector? that you should be aware of.
 

ThreadLocal

The java.lang.ThreadLocal class provides a convenient way for an instance to have per-Thread data. This allows you to avoid the need for synchronization because data is not shared between threads, each thread has it's own set of data. I've found this to be very helpful for caching results, let me give an example.
Line: 49 to 49
 

Discussion about SynchronizationIsSlowMisconception

Added:
>
>
I can't follow your example in "Understanding your Application" could you please explain it again? Maybe with an example? (TZ?)
 

 <<O>>  Difference Topic SynchronizationIsSlowMisconception (3 - 16 Jun 2003 - Main.leknor)
Line: 1 to 1
 
META TOPICPARENT name="Misconceptions"
Home | Help | Changes | Index | Search | Go
Line: 13 to 13
 Contention happens when two threads compete for one resource, in Java that resource is an instance of an Object. When one thread has acquired a lock on an object and is still holding on to it, contention happens when another thread also tries to acquire a lock on the same object. The second thread is blocked until the first thread had released it's lock. This allows the second thread to acquire a lock and move forward.

What is the cost of Synchronization without Contention

Changed:
<
<
// TODO: give an overview of what the JVM has to do and reference some numbers on uncontented overhead.
>
>
No matter what, when a Thread enters a synchronized block it must test for and acquire a lock. In newer JVMs (1.4.0) this cost is very small. So small that the slight implementation differences in java.util.Vector.set(int,Object) and java.util.ArrayList.set(int,Object) make the Vector faster in the 1.4.0-sever mode despite the fact that Vector's set method is synchronized and ArrayList's set method is not. See Java Performance Tuning page 291for more info.
 

What is the cost of Synchronization with Contention

The overwhelming cost of contention is the time spent idle waiting to acquire a lock. During this time a thread cannot move foreword and continue to do work. This means that the cost of synchronization with contention includes the work done by any threads that acquire the lock on an object before this thread can continue. For any non-trivial application, the amount of work done in normal program flow completely dwarfs the work needed to acquire synchronization locks by orders of magnitude?.
Line: 33 to 33
 I once wrote a Java Servlet? that transformed XML into HTML. The result of first few steps were the exact same every time but the result of those steps was not thread safe. So, I used ThreadLocal so that each thread could have it's own set of cached data and didn't have to synchronize access to the Servlet. The benefit of not having to repeat a lot of work plus the ability to take advantage of all CPU?s gave a good performance boost at the cost of increased memory consumption.

Understanding your Application

Changed:
<
<
// TODO: understand the application's behavior and the probability of contention for any one object instance.
>
>
The Small Synchronized Blocks suggestion above is very common becase it's easy to implement and won't have large negative effects if implemented poorly. Each time the code crosses a synchronized boundary it must do the work to test for and acquire the lock. While this process is cheap, it is not free. If it is known that a shared resource is not likely to be contended for by many threads then it may be desireable to only synchronize once on that resource while doing work instead of many times on that resource while doing work.
 

Summary

Changed:
<
<
// TODO: write me
>
>
The cost of syncronization is very small. The cost of contention can be large. If you compare the source of Vector.set(...) and ArrayList.set(...) you'll see that the overhead of syncronization is less that the cost of a private method call and an integer comparision in a boolean expression. Pick a faster algorithm and don't get hung up on if it needs to be synchronized for correctness. Do consider the implications of contention when picking an algorithm.
 
Changed:
<
<

Misunderstood Arguments against Synchronization

// TODO: Synchronization prevents optimizations.

External Resources

>
>

References

 
Changed:
<
<
-- SandyMcArthur - 12 Jun 2003
>
>
-- SandyMcArthur - 16 Jun 2003
 


 <<O>>  Difference Topic SynchronizationIsSlowMisconception (2 - 12 Jun 2003 - Main.leknor)
Line: 1 to 1
 
META TOPICPARENT name="Misconceptions"
Home | Help | Changes | Index | Search | Go
Line: 19 to 19
 The overwhelming cost of contention is the time spent idle waiting to acquire a lock. During this time a thread cannot move foreword and continue to do work. This means that the cost of synchronization with contention includes the work done by any threads that acquire the lock on an object before this thread can continue. For any non-trivial application, the amount of work done in normal program flow completely dwarfs the work needed to acquire synchronization locks by orders of magnitude?.

The Solutions

Changed:
<
<
You cannot avoid synchronization when it's needed. If the algorithm you've chosen to implement requires synchronization for correct behavior, then you must use synchronization; Otherwise you allow for possibly very subtle bugs. You can change your algorithm to one that does not require synchronization but this should be avoided unless it is understood that the possible algorithmic optimizations you are giving up are not significant. I personally consider blind avoidance of synchronization to be the same evil as premature optimization.
>
>
You cannot avoid synchronization when it's needed. If the algorithm you've chosen to implement requires synchronization for correct behavior, then you must use synchronization; otherwise you allow for possibly very subtle bugs. You can change your algorithm to one that does not require synchronization but this should be avoided unless it is understood that the possible algorithmic optimizations you are giving up are not significant. I personally consider blind avoidance of synchronization to be the same evil as premature optimization.
 

Small Synchronized Blocks

One very common synchronization advice is to make your synchronized blocks as small as possible. In other words, you are doing as little work as possible inside of a synchronized block of code. The rationale is that since the cost of contention is relativity so expensive, don't worry about other synchronization costs. Also, this method does not require a full understanding of your application's behavior. The downside to this method is that the repeated acquisition and release of synchronization locks may be more expensive than contention if contention is extremely rare or not possible, like a single threaded application.
Added:
>
>

Immutable Objects

An immutable object cannot change value once it's been created. The java.lang.String is the most common example of an immutable object. Since an immutable object cannot be modified it is safe to share these objects between threads without the use of synchronization. Depending on thier use immutable objects have other performance implications with respect to the garbage collector? that you should be aware of.
 

ThreadLocal

The java.lang.ThreadLocal class provides a convenient way for an instance to have per-Thread data. This allows you to avoid the need for synchronization because data is not shared between threads, each thread has it's own set of data. I've found this to be very helpful for caching results, let me give an example.
Line: 42 to 45
 
Changed:
<
<
By: SandyMcArthur
>
>
-- SandyMcArthur - 12 Jun 2003
 


 <<O>>  Difference Topic SynchronizationIsSlowMisconception (1 - 10 Jun 2003 - Main.leknor)
Line: 1 to 1
Added:
>
>
META TOPICPARENT name="Misconceptions"
Home | Help | Changes | Index | Search | Go

SynchronizationIsSlowMisconception

Introduction

It has been repeated that synchronization is slow many times to the point that many people will go to great lengths to avoid synchronization without a full understanding of what they are avoiding. Synchronization is not free, there is a cost associated with it, but modern JVMs make it very cheap. What is expensive is contention.

What is Contention

Contention happens when two threads compete for one resource, in Java that resource is an instance of an Object. When one thread has acquired a lock on an object and is still holding on to it, contention happens when another thread also tries to acquire a lock on the same object. The second thread is blocked until the first thread had released it's lock. This allows the second thread to acquire a lock and move forward.

What is the cost of Synchronization without Contention

// TODO: give an overview of what the JVM has to do and reference some numbers on uncontented overhead.

What is the cost of Synchronization with Contention

The overwhelming cost of contention is the time spent idle waiting to acquire a lock. During this time a thread cannot move foreword and continue to do work. This means that the cost of synchronization with contention includes the work done by any threads that acquire the lock on an object before this thread can continue. For any non-trivial application, the amount of work done in normal program flow completely dwarfs the work needed to acquire synchronization locks by orders of magnitude?.

The Solutions

You cannot avoid synchronization when it's needed. If the algorithm you've chosen to implement requires synchronization for correct behavior, then you must use synchronization; Otherwise you allow for possibly very subtle bugs. You can change your algorithm to one that does not require synchronization but this should be avoided unless it is understood that the possible algorithmic optimizations you are giving up are not significant. I personally consider blind avoidance of synchronization to be the same evil as premature optimization.

Small Synchronized Blocks

One very common synchronization advice is to make your synchronized blocks as small as possible. In other words, you are doing as little work as possible inside of a synchronized block of code. The rationale is that since the cost of contention is relativity so expensive, don't worry about other synchronization costs. Also, this method does not require a full understanding of your application's behavior. The downside to this method is that the repeated acquisition and release of synchronization locks may be more expensive than contention if contention is extremely rare or not possible, like a single threaded application.

ThreadLocal

The java.lang.ThreadLocal class provides a convenient way for an instance to have per-Thread data. This allows you to avoid the need for synchronization because data is not shared between threads, each thread has it's own set of data. I've found this to be very helpful for caching results, let me give an example.

I once wrote a Java Servlet? that transformed XML into HTML. The result of first few steps were the exact same every time but the result of those steps was not thread safe. So, I used ThreadLocal so that each thread could have it's own set of cached data and didn't have to synchronize access to the Servlet. The benefit of not having to repeat a lot of work plus the ability to take advantage of all CPU?s gave a good performance boost at the cost of increased memory consumption.

Understanding your Application

// TODO: understand the application's behavior and the probability of contention for any one object instance.

Summary

// TODO: write me

Misunderstood Arguments against Synchronization

// TODO: Synchronization prevents optimizations.

External Resources

By: SandyMcArthur



Discussion about SynchronizationIsSlowMisconception


Topic SynchronizationIsSlowMisconception . { View | Diffs r7 < r6 < r5 < r4 | More }
 XML java.net RSS