Collections and Decorators

A

ankur

Hi All,

I did not understand why do we need to use the Decorators for
Collections for thread safety ?

so if I have a Collection c

why can't I just do:

synchronized(c) {

//do something on the collection c

}

for thread safety, rather than having to do instead

Collection sync_c = Collections.synchronizedCollection(c);

synchronized(sync_c) {

//do something on the collection sync_c

}

Thanks,
Ankur
 
M

Mark Space

ankur said:
for thread safety, rather than having to do instead

Collection sync_c = Collections.synchronizedCollection(c);

synchronized(sync_c) {

//do something on the collection sync_c

}


You don't. Once you do

Collection sync_c = Collections.synchronizedCollection(c);

// do something on the collection sync_c

You don't need to used "synchronized()" explicitly any more. The
collection itself does it for you.

Note if you have an operation that takes more than one call -- like
read-modify-write -- you still have to synchronize on the collection for
the entire operation.
 
L

Lew

ankur said:
I did not understand why do we need to use the Decorators for
Collections for thread safety ?

You don't have to.
so if I have a Collection c

why can't I just do:

synchronized(c) {

//do something on the collection c

}

Ah, but you can, and sometimes you have to.
for thread safety, rather than having to do instead

Collection sync_c = Collections.synchronizedCollection(c);

synchronized(sync_c) {

//do something on the collection sync_c

}

It isn't a question of can you do that, it's a question of when should you do
that.

There are multiple synchronization strategies. The use of
'Collections.synchronizedX()' only synchronizes most of the public method
calls; it doesn't resolve every possible synchronization issue, nor is it the
only way to synchronize the collection.

Proper concurrency-aware programming is one of the Dark Arts.
 
A

ankur

You don't.  Once you do

   Collection sync_c = Collections.synchronizedCollection(c);

   // do something on the collection sync_c

You don't need to used "synchronized()" explicitly any more.  The
collection itself does it for you.

Note if you have an operation that takes more than one call -- like
read-modify-write -- you still have to synchronize on the collection for
the entire operation.

Ok, so why doesn't this
Collection sync_c = Collections.synchronizedCollection(c);
take care of everything ? I mean even after I have sync_c why am I
still required to synchronize on the collection "for an operation that
takes more than one call -- like read-modify - execute". Using an
iterator is one example.

Is this due to some incomplete implementation ? I know I can look at
the source code but before I did that I wanted to ask this so as to
make sure I am not missing any subtle point.
-Ankur
 
A

ankur

You don't have to.






Ah, but you can, and sometimes you have to.

So Lew can I always use synchronized(c) and rest assured that my
operations on the collection would not be thread safe. I meant, can I
avoid using Collections.synchronizedCollection(c) by using an
equivalent code block that just uses synchronized(c) construct. Can
you please give me an example where I will have to necessarily use
Collections.synchronizedCollection(c) and I will not be able to get by
just using
synchronized(c)
{
}

-Ankur
 
J

Joshua Cranmer

ankur said:
Hi All,

I did not understand why do we need to use the Decorators for
Collections for thread safety ?
why can't I just do:

synchronized(c) {

//do something on the collection c

}

You can do that and still be thread-safe. The catch, of course, is that
you have to make sure others using the map are also synchronizing on
said object.

This is the wonderful world of multithreaded programming, an area where
even experts can do things incorrectly. Having synchronized blocks alone
does not guarantee thread safety--you can still create paralyzing
deadlocks with synchronized blocks. It is also possible in a number of
cases to achieve thread safety without synchronization, but getting
these rights requires a certain level of expertise and knowledge that is
not generally taught.
 
A

ankur

Ok, so why doesn't this
Collection sync_c = Collections.synchronizedCollection(c);
take care of everything ? I mean even after I have sync_c why am I
still required to synchronize on the collection "for an operation that
takes more than one call -- like read-modify - execute". Using an
iterator is one example.

Is this due to some incomplete implementation ? I know I can look at
the source code but before I did that I wanted to ask this so as to
make sure I am not missing any subtle point.
-Ankur- Hide quoted text -

- Show quoted text -

In Collections.java this code snippet is present :

public Iterator<E> iterator() {
return c.iterator(); // Must be manually synched by user!
}

So, thats why Iterator operations need to manually synched. But my
question is why was this left unsynched in Java ? All other public
methods are synched on Object mutex in the static class

static class SynchronizedCollection<E>

--Ankur
 
M

Mark Space

ankur said:
Ok, so why doesn't this
Collection sync_c = Collections.synchronizedCollection(c);
take care of everything ?


It can't.

All synchronized collection does is wrap calls to Collection methods
like this:

@Override
public synchronized boolean add( E e ) {
internal.add( e );
}

where "internal" is the collection you wrapped. That's all the code is
capable of doing. It doesn't know that you might want to do something
else with the collection after add() completes, and anyway
synchronization in Java is in blocks and automatically releases once the
block is exited.

What it can't do is this:

if( sync_c.contains( object ) ) {
sync_c.remove( object )
}

because in between the call to "contains" and "remove" another thread
might modify the sync_c and you can't control that. Thus, the external
lock is required:

synchronized( sync_c ) {
if( sync_c.contains( object ) ) {
sync_c.remove( object )
}
}

Same with iterators -- you have to lock manually because the code inside
sync_c doesn't know, can't know, when you are done using the iterator.
 
L

Lew

ankur said:
So Lew can I always use synchronized(c) and rest assured that my
operations on the collection would not be thread safe.

I'm having a hard time endorsing the association of "rest assured" with "not
.... safe".

Regardless, the answer is no.

Remember the part of my message that said?
I meant, can I avoid using Collections.synchronizedCollection(c) by using an

Why do you wish to avoid it?
equivalent code block that just uses synchronized(c) construct.

Under what circumstances does that give you an advantage?
What advantage?
What dangers or other collateral impact does it have?
Can you please give me an example where I will have to necessarily use
Collections.synchronizedCollection(c) and I will not be able to get by
just using
synchronized(c)
{
}

"just" using?

What do you see as the differences, pro and con, in your analysis?

Remember,
For example, suppose what you need is a concurrent HashMap. You could:

Map <Foo, Bar> associations = new HashMap <Foo, Bar> ();
Map <Foo, Bar> synchAssns = Collections.synchronizedMap( associations );
Map <Foo, Bar> concurrences = new ConcurrentHashMap <Foo, Bar> ();
....
public Bar get( Foo foo )
{
synchronized( associations ) { return associations.get( foo ); }
}
public Bar getSynch( Foo foo )
{
return synchAssns.get( foo );
}
public Bar getConcur( Foo foo )
{
return concurrences.get( foo ); }
}

There really is no one-size-fits-all for every concurrency situation. You
have to think very carefully about your particular scenario.

Please do not quote sigs.
 
J

Joshua Cranmer

ankur said:
So, thats why Iterator operations need to manually synched. But my
question is why was this left unsynched in Java ? All other public
methods are synched on Object mutex in the static class

Please explain to me how to properly synchronize an iterator in a
wrapper like this. The purpose of synchronization is to ensure that
modifications are atomic and so will not be modified by other threads.
SynchronizedCollection can only provide method-level synchronization by
its inherent design. For an iterator, the atomicity that would need to
be implied is the entire iteration. The implementation cannot force
synchronization across multiple methods, so the caller must provide the
needed synchronization.

It is true that an iterator with a very complex next() or hasNext()
methods might benefit from synchronization, but the contract is already
implying that the user must synchronize around the iteration in the
first place, so such a lock would be merely redundant.
 
N

neuneudr

Hi All,

I did not understand why do we need to use the Decorators for
Collections for thread safety ?
"the Decorators"

As a nitpick there's really no need to capitalize the first
letter of "decorator" and, anyway, in the OO sense, you're
not decorating anything but merely "wrapping" it.

All decorators uses wrapped object, but all construct using
wrappers are *definitely NOT* decorators.

The terminology used in the Javadocs is correct btw, where
they're referring to "wrappers", not decorators.

When talking about "decorator" one is usually referring to
the decorator design pattern, which is either about adding
*or* (less known) removing functionnality at the OO level.

Synchronization has *nothing* to do with OO-analysis nor
OO-design (it simply doesn't exist at the OOA/OOD level).

Referring to the wrappers Collections.synchronizedXXX(...)
as "Decorators" is incorrect.

The Javadocs are correct.
 
A

ankur

As a nitpick there's really no need to capitalize the first
letter of "decorator" and, anyway, in the OO sense, you're
not decorating anything but merely "wrapping" it.

All decorators uses wrapped object, but all construct using
wrappers are *definitely NOT* decorators.

The terminology used in the Javadocs is correct btw, where
they're referring to "wrappers", not decorators.

When talking about "decorator" one is usually referring to
the decorator design pattern, which is either about adding
*or* (less known) removing functionnality at the OO level.

Synchronization has *nothing* to do with OO-analysis nor
OO-design (it simply doesn't exist at the OOA/OOD level).

Referring to the wrappers Collections.synchronizedXXX(...)
as "Decorators" is incorrect.

The Javadocs are correct.

Ok, I get it. Thank you all.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,781
Messages
2,569,615
Members
45,296
Latest member
HeikeHolli

Latest Threads

Top