Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Multiple writers, one reader, which collection

My situation is this:

Multiple threads must write concurrently to the same collection (add and addrange). Order of items is not an issue. When all threads have completed (join) and im back on my main thread, then I need to read all the collected data fast in a foreach style, where no actual locking is needed since all threads are done.

In the "old days" I would probably use a readerwriter lock for this on a List, but with the new concurrent collections I wonder if not there is a better alternative. I just can't figure out which as most concurrent collections seem to assume that the reader is also on a concurrent thread.

like image 891
Christian Mikkelsen Avatar asked Feb 01 '13 02:02

Christian Mikkelsen


2 Answers

I don't believe you want to use any of the collections in System.Collections.Concurrent. These generally have extra overhead to allow for concurrent reading.

Unless you have a lot of contention, you are probably better taking a lock on a simple List<T> and adding to it. You will have a small amount of overhead as the List resizes, but it will be fairly infrequent.

However, what I would probably do in this case is simply adding to a List<T> per thread rather than a shared one, and either merge them at the end of processing, or simply iterate over all elements in each of the collections.

You could possibly use a ConcurrentBag and then call .ToArray() or GetEnumerator() on it when ready to read (bypassing a per-read penalty), but you will may find that the speed of insertions is a bit slower than your manual write lock on a simple List. It really depends on amount of contention. The ConcurrentBag is pretty good about partitioning but as you noted, is geared to concurrent reads and writes.

As always, benchmark your particular situation! Multithreading performance is highly dependent on many things in actual usage, and things like type of data, number of insertions, and such will change the results dramatically - a handful of reality is worth a gallon of theory.

like image 59
Philip Rieck Avatar answered Oct 20 '22 04:10

Philip Rieck


Order of items is not an issue. When all threads have completed (join) and im back on my main thread, then I need to read all the collected data

You have not stated a requirement for a thread-safe collection at all. There's no point in sharing a single collection since you never read at the same time you write. Nor does it matter that all writing happens to the same collection since order doesn't matter. Nor should it matter since order would be random anyway.

So just give each thread its own collection to fill, no locking required. And iterate them one by one afterwards, no locking required.

like image 41
Hans Passant Avatar answered Oct 20 '22 05:10

Hans Passant