Synchronized collection

D

David

I'd like to have a collection where access to the elements is synchronized.
Looking at the API, it seems that many collections aren't synchronized by
default but that it is possible to obtain a synchronized collection by
calling, for example, Collections.synchronizedSet(Set s).

Are there any disadvantages to doing the above? Is the returned set fully
thread-safe - eg. are the add and remove methods synchronized? Is there a
better alternative?

The reason I ask is that it seems a common requirement to have synchronized
collections and I'm surprised you have to rely on a static method within the
Collections Class.

Thanks for any advice,
David
 
B

Bent C Dalager

Are there any disadvantages to doing the above? Is the returned set fully
thread-safe - eg. are the add and remove methods synchronized? Is there a
better alternative?

It is quite safe. By using that method, you are losing any extra nifty
interface your particular Set implementation might have since the
returned value is a vanilla Set. And you must take care not to use the
original object for anything (to be safe, just forget its reference)
or you'll risk breaking the synchronization.
The reason I ask is that it seems a common requirement to have synchronized
collections and I'm surprised you have to rely on a static method within the
Collections Class.

The basic collection implementations aren't thread safe for two basic
reasons. First, they would be slightly slower if they were and lots of
people don't need thread-safeness. Second, synchronization used
without care will tend to lead to deadlock and that seems rather a
harsh punishment for the hapless programmer to incur simply for using
a collection class.

Cheers
Bent D
 
A

Adam Maass

Bent C Dalager said:
It is quite safe. By using that method, you are losing any extra nifty
interface your particular Set implementation might have since the
returned value is a vanilla Set. And you must take care not to use the
original object for anything (to be safe, just forget its reference)
or you'll risk breaking the synchronization.


The basic collection implementations aren't thread safe for two basic
reasons. First, they would be slightly slower if they were and lots of
people don't need thread-safeness. Second, synchronization used
without care will tend to lead to deadlock and that seems rather a
harsh punishment for the hapless programmer to incur simply for using
a collection class.

.... and, synchronizing on individual methods in the collection class often
isn't enough. (IE, the collection isn't the right object on which to
synchronize.)

Consider a class that maintains two lists, one for "active" objects and one
for inactive objects (and no object should be in both lists at once:

class Foo
{
private List active...
private List inactive...

void activate(Object o)
{
inactive.remove(o);
active.add(o);
}

void inactivate(Object o)
{
active.remove(o);
inactive.add(o);
}
}

Even if the individual lists are synchronized, it is possible that, should
the activate and inactive methods be called concurrently with the same
argument, the same object would end up in both lists.

The correct place to synchronize here is on the Foo object itself, not on
the lists. Since access to the lists is already synchronized, there is no
reason that the methods on the lists should themselves be synchronized.



-- Adam Maass
 
J

John C. Bollinger

David said:
I'd like to have a collection where access to the elements is synchronized.
Looking at the API, it seems that many collections aren't synchronized by
default but that it is possible to obtain a synchronized collection by
calling, for example, Collections.synchronizedSet(Set s).

Are there any disadvantages to doing the above? Is the returned set fully
thread-safe - eg. are the add and remove methods synchronized? Is there a
better alternative?

From the API docs for Collections.synchronizedSet(Set):
----
Returns a synchronized (thread-safe) set backed by the specified set. In
order to guarantee serial access, it is critical that all access to the
backing set is accomplished through the returned set.

It is imperative that the user manually synchronize on the returned set
when iterating over it:

[...]
----

Disadvantage: performance might be poorer than you could get with a
custom thread-safe Set implementation. On the other hand, you don't
have to worry about writing your own implementation or manual
synchronization.

Alternatives: For a Set, you can use one of the standard Sets and
manually synchronize all accesses. If you want to be daring and invite
bugs, you could even pick and choose which accesses really need to be
synchronized and which don't. If you were talking about a List instead
then Vector is a List that is inherently synchronized. Likewise a
HashTable vis a vis a HashMap.
The reason I ask is that it seems a common requirement to have synchronized
collections and I'm surprised you have to rely on a static method within the
Collections Class.

As I pointed out, there _are_ synchronized implementations of List and
Map. The Collections class provides a way to obtain a synchronized,
appropriately typed view of any Collection, including third-party
implementations. That there is no built-in synchronized Set is largely
an historic artifact. (Or really, the fact that there are any
inherently synchronized Collection implementations is the artifact.)
Synchronization places run-time demands on the VM that can be quite
expensive, which is why the standard Collections are not inherently
synchronized; the synchronized views provided by the Collections class
solve the problem generically for those cases where synchronized
implementations are required.


John Bollinger
(e-mail address removed)
 

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,773
Messages
2,569,594
Members
45,123
Latest member
Layne6498
Top