0

I have read that access to Collection instances should not be synchronised within a class. The reason seems to be that another object might manipulate the list, without synchronising to the first object. However, the List I want synchronised is a private field, is created by the owner object, and has no accessor methods.

I am using two inner classes, a producer and a consumer, which each implement class Runnable and run in a separate thread. Whenever they access the list belonging to the parent class, they will synchonise on the parent class.

Furthermore, my implementation only uses a single instance of the parent class, and one each of the inner classeses.

Is it acceptable, then, simply to use synchronise blocks to control access? Or is this still a no-no?

I don't think I can use a synchronisedList. The reason is that the consumer thread consumes in bulk: it first sorts using Collections.Sort and a comparator, then uses the subList method to get a list of the first 20 (by default) objects in the list (it actually creates a new list, by passing the subList call to an ArrayList constructor), and then passes the list returned by subList to removeAll of the original list:

Collections.sort(pool, examComparator);

List<Candidate> squad = new ArrayList<Candidate>(pool.subList(0, squadSize));
pool.removeAll(squad);

return squad;

Since this is a multi-step operation, and needs to be atomic, I can't see how it would be facilitated by synchronisedList, which (as I understand it) simply provides synchronisation for individual method calls such as add() and get().

3
  • 2
    There's nothing wrong with synchronizing on the List itself and using a block, as long you you prevent any access to it without doing so. Commented Feb 13, 2013 at 2:21
  • have you tried the observer pattern? en.wikipedia.org/wiki/Observer_pattern Commented Feb 13, 2013 at 2:23
  • leojg: I don't think the observer pattern fits my project. Both producer and consumer work independently of one another, and it is assumed that there will always be more objects in the list than will be removed at any one time (i.e. there will always be leftovers). So the consumer doesn't wait for the producer to add before it consumes (although it will check that there are actually things to be consumed, just in case) Commented Feb 13, 2013 at 2:31

1 Answer 1

1

The java.util.concurrent package has everything you need to avoid writing your own code and re-inventing the wheel.

Use a CopyOnWriteArrayList for your list implementation and it's job done.

Writing threadsafe implementations is definitely non-trivial, and these classes have been written to be safe and as efficient as possible.

edit:

If you have a producer consumer model, use a BlockingQueue.

Sign up to request clarification or add additional context in comments.

2 Comments

The doco says this class is suitable "when traversal operations vastly outnumber mutations". Since my producer is adding objects one-by-one, much more frequently than the consumer batch-consumes, I'd imagine copying the entire array each time wouldn't be all that efficient. I'd prefer to keep the structure this way rather than having the producer batch-produce.
If you have a producer consumer model, use a ArrayBlockingQueue. D

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.