Adding to list from multiple threads?

time to read 2 min | 370 words

I just read an email from someone that assume that it is safe to access a collection from multiple threads, if this is done for adding items to the collection only.

My gut feeling said that this is a bad idea, but I set out to verify it anyway. Here is the test case: 

static void Main(string[] args)
{
    List<int> ints = new List<int>();
    ManualResetEvent resetEvent = new ManualResetEvent(false);
    int additions = 0;
    int totalCount = 1000000;
    for (int i = 0; i < totalCount; i++)
    {
        int tmp = i;//check C# spec for reasons
        ThreadPool.QueueUserWorkItem(delegate
         {
             resetEvent.WaitOne();
             ints.Add(tmp);
Interlocked.Increment(ref additions); }); } Console.WriteLine("Starting to add..."); resetEvent.Set(); while (additions < totalCount) Thread.Sleep(200); Console.WriteLine(additions); Console.WriteLine(ints.Count); }

It is a bit tricky, because all code that deals with multi threading is tricky, but basically I am trying to create as much contention as possible, and on my machine (dual core), I get the following results:

Starting to add...
1000000
999812

So the answer is pretty clear, it is not safe to access a collection from multiply threads without proper locks, not matter what you do to it. I had to increate the totalCount significantly before I could get a reproducible result, but this happened at much lower iteration counts as well, so don't think that you can get away with it if you have small collections.

Working with threads requires thread synchronization, always.