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 [EMAIL PROTECTED] http://www.whirlycott.com/phil/

---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]



Reply via email to