commons-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From WHIRLYCOTT <p...@whirlycott.com>
Subject Re: concurrency and starting a synchronized block
Date Thu, 10 Feb 2005 18:09:14 GMT
I spent a whole bunch of time looking into how various 
caches/collections handled this issue when I was designing Whirlycache 
[1] and the cleanest solution that is available today, as others have 
pointed out, is Doug Lea's util.concurrent package.

The high-level explanation of how Doug Lea's ConcurrentHashMap works is 
that it has 32 internal buckets and a fast hashing algorithm.  It only 
synchronizes internally on the bucket that is being modified, thereby 
leaving the other n buckets free to do whatever they need.  So you can 
conceivably have 32 concurrent threads reading and/or writing depending 
on how the hashing algorithm causes the buckets to be synchronized.

It's a lot faster than a java.util.HashMap when you have many threads 
reading and writing.

I think the 32 fixed bucket size limit was removed when these classes 
were ported to JDK 1.5.

Depending on what you are doing, you basically have 3 choices when 
you're dealing with multithreaded access/modification to a collection:

1) don't synchronize and watch failures happen

2) synchronize on the containing object's monitor:

	...
	public synchronized whatever(Object arg1) {...}
	public synchronized something() {...}
	...

3) use more granular synch locks, if possible:

	...
	private Object whatever = new Object();
	private Object something = new Object();

	public whatever(Object arg1) {
	  synchronized (whatever) {
		...
	  }
	}

	public something(Object arg1) {
	  synchronized (something) {
		...
	  }
	}

Making the locks more granular can make a huge difference, but it's only 
possible if your particular case will allow for it.  But it's definitely 
worth investigating rather than blindly using 'synchronized' in method 
signatures... which turns out to be not-that-slow anyway.

YMMV.

phil.

	[1] http://whirlycache.dev.java.net/

Torsten Curdt wrote:
> Guys, forgive me if this too off topic...
> 
> ...but I thought it is somehow related to
> collections that's why I am bringing it up
> here anyway. I bet someone of you will know....
> 
> Consider this code...
> 
>  Object o = map.get(key);
>  if (o == null) {
>    synchronized(map) {
>      map.put(key,new Object());
>    }
>  }
> 
> 99% of the time the "get"s on the map are going
> to return an object. That's why I would like
> to avoid synchronizing the "get" access.
> Now since a "put" might corrupt the data it
> has to be synchronized.
> 
> Since the "get", the comparison and the "put"
> are not in a synchronized block I might loose
> objects ...but for this particular usecase
> that's ok.
> 
> Now what really got me thinking is the
> concurrent sychronized and non-synchronized
> access.
> 
> What happens when Thread A is in doing a
> "get" while Thread B is entering the
> sychronized block for the "put"?
> 
> I assume that since the map object is not
> locked it will go straight into the "put"
> and bang ...right?
> 
> Somehow this looks like the optimal usecase
> for the FastHashMap from collections ...but
> since this code needs to be very portable
> this might be a problem because of the
> double-checked locking idiom.
> 
> Another option would be using the StaticBucketMap.
> 
> What do you guys think?
> 
> If you consider this too OT please reply off list.
> 
> cheers
> -- 
> Torsten

-- 
                                   Whirlycott
                                   Philip Jacob
                                   phil@whirlycott.com
                                   http://www.whirlycott.com/phil/

---------------------------------------------------------------------
To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: commons-dev-help@jakarta.apache.org


Mime
View raw message