Are C# arrays thread safe?

C#MultithreadingArraysThread Safety

C# Problem Overview


In particular

  1. Create a function to take an array and an index as parameters.
  2. Create a n element array.
  3. Create a n count loop.
  4. Inside the loop on a new thread assign a new instance of the object to the array using the indexer passed in.

I know how to manage the threads etc. I am interested in know if this is thread safe way of doing something.

 class Program
{
    // bogus object
    class SomeObject
    {
        private int value1;
        private int value2;

        public SomeObject(int value1, int value2)
        {
            this.value1 = value1;
            this.value2 = value2;
        }
    }
   
    static void Main(string[] args)
    {

        var s = new SomeObject[10];
        var threads = Environment.ProcessorCount - 1;
        var stp = new SmartThreadPool(1000, threads, threads);
        for (var i = 0; i < 10; i++)
        {
            stp.QueueWorkItem(CreateElement, s, i);
        }

    }

    static void CreateElement(SomeObject[] s, int index)
    {
        s[index] = new SomeObject(index, 2);
    }
}

C# Solutions


Solution 1 - C#

I believe that if each thread only works on a separate part of the array, all will be well. If you're going to share data (i. e. communicate it between threads) then you'll need some sort of memory barrier to avoid memory model issues.

I believe that if you spawn a bunch of threads, each of which populates its own section of the array, then wait for all of those threads to finish using Thread.Join, that that will do enough in terms of barriers for you to be safe. I don't have any supporting documentation for that at the moment, mind you ...

EDIT: Your sample code is safe. At no time are two threads accessing the same element - it's as if they each have separate variables. However, that doesn't tend to be useful on its own. At some point normally the threads will want to share state - one thread will want to read what another has written. Otherwise there's no point in them writing into a shared array instead of into their own private variables. That's the point at which you need to be careful - the coordination between threads.

Solution 2 - C#

MSDN documentation on Arrays says:

> Public static (Shared in Visual Basic) > members of this type are thread safe. > Any instance members are not > guaranteed to be thread safe. > > This implementation does not provide a > synchronized (thread safe) wrapper for > an Array; however, .NET Framework > classes based on Array provide their > own synchronized version of the > collection using the SyncRoot > property. > > Enumerating through a collection is > intrinsically not a thread-safe > procedure. Even when a collection is > synchronized, other threads can still > modify the collection, which causes > the enumerator to throw an exception. > To guarantee thread safety during > enumeration, you can either lock the > collection during the entire > enumeration or catch the exceptions > resulting from changes made by other > threads.

So no, they're not thread safe.

Solution 3 - C#

Generally when a collection is said to be 'not threadsafe' that means that concurrent accesses could fail internally (e.g. it not safe to read the first element of List<T> while another thread adds an element at the end of the list: the List<T> might resize the underlying array and the read access might go to the new array before the data was copied into it).

Such errors are impossible with arrays because arrays are fixed-size and have no such 'structure changes'. An array with three elements is no more or less thread-safe than three variables.

The C# specification doesn't say anything about this; but it is clear if you know IL and read the CLI specification - you could get a managed reference (like those used for C# "ref" parameters) to an element inside an array and then do both normal and volatile loads and stores to it. The CLI spec describes the thread-safety guarantees for such loads and stores (e.g. atomicity for elements <=32 bit)

So if I'm unterstanding your question correctly, you want to fill an array using different threads, but will assign to each array element only once? If so, that's perfectly thread-safe.

Solution 4 - C#

The example you are providing is very similar to the way that Microsoft's own Parallel extensions to C# 4.0 work.

This for loop:

for (int i = 0; i < 100; i++) { 
  a[i] = a[i]*a[i]; 
}

becomes

Parallel.For(0, 100, delegate(int i) { 
  a[i] = a[i]*a[i]; 
});

So, yes, your example should be OK. Here's an older blog post about the new parallel support in C#.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionGaryView Question on Stackoverflow
Solution 1 - C#Jon SkeetView Answer on Stackoverflow
Solution 2 - C#JorenView Answer on Stackoverflow
Solution 3 - C#DanielView Answer on Stackoverflow
Solution 4 - C#EricView Answer on Stackoverflow