Justin Mathew
Justin Mathew

Reputation: 335

C# Readonly List thread Synchronisation

What I am doing here is navigating a read-only list by for-each and by index method in multiple threads. The result looks thread safe, but I'm not convinced.

Could anybody please tell the below code (reading from read-only list) is thread safe or not? if yes then why?

public class ThreadTest
{
   readonly List<string> port;

    public  ThreadTest()
    {
        port = new List<string>() { "1", "2", "3", "4", "5", "6" };            
    }

    private void Print()
    {
        foreach (var itm in port)
        {
            Thread.Sleep(50);
            Console.WriteLine(itm+"----"+Thread.CurrentThread.ManagedThreadId);
        }
    }

    private void Printi()
    {
        for(int i=0;i<5;i++)
        {
            Thread.Sleep(100);
            Console.WriteLine(port[i] + "--iiiii--" + Thread.CurrentThread.ManagedThreadId);
        }
    }

    public void StartThread()
    {
        Task[] tsks = new Task[10];
        tsks[0] = new Task(Print);
        tsks[1] = new Task(Print);
        tsks[2] = new Task(Print);
        tsks[3] = new Task(Print);
        tsks[4] = new Task(Print);
        tsks[5] = new Task(Printi);
        tsks[6] = new Task(Printi);
        tsks[7] = new Task(Printi);
        tsks[8] = new Task(Printi);
        tsks[9] = new Task(Printi);

        foreach (var tsk in tsks)
        {
            tsk.Start();
        }

        Task.WaitAll(tsks);
    }
}

class Program
{
    static void Main(string[] args)
    {

        new ThreadTest().StartThread();

        Console.ReadLine();
    }
}

Upvotes: 2

Views: 1777

Answers (3)

Diogo Machado
Diogo Machado

Reputation: 61

If it is not documented to be thread safe then don't assume it is!

I'll give you an example that illustrates why you shouldn't assume it unless it is documented:

Suppose that internally, the List is a LinkedList of nodes, each node containing a string with the value. The method Search(string value), has to iterate through the nodes to find if the value exists. apparently there is no thread safety issue here.

But now, imagine, for a performance optimization reason, that the List keeps an internal array where the last values searched are written, this can be useful to immediately check values most commonly search.

Do you see what we made here? now a read changes the internal state of the list, and mutations are not thread safe.

Usually, data structures do not do mutations on reads, but you cannot rely upon that unless it is documented!

In this particular case of List usage, the msdn says, as already mentioned:

It is safe to perform multiple read operations on a List, but issues can occur if the collection is modified while it’s being read. To ensure thread safety, lock the collection during a read or write operation. To enable a collection to be accessed by multiple threads for reading and writing, you must implement your own synchronization. For collections with built-in synchronization, see the classes in the System.Collections.Concurrent namespace. For an inherently thread–safe alternative, see the ImmutableList class.

giving that, yes you can do multiple reads with no writes in a thread safe manner, but don't assume it unless it is documented.

If you want to use a List only to read, i suggest you to wrap it with a class that exposes only read operations over the list, this will ensure that no code, by accident, changes the list.

Upvotes: 0

atlanteh
atlanteh

Reputation: 5835

If no one changes the list why would it not be thread safe? the only problem I see here is if (You are superman and) you press the key faster than the threads read the list and then some of them will be killed with the main.
So it's better to wait for them to finish before main finishes.

Upvotes: -1

Eric J.
Eric J.

Reputation: 150108

It is considered thread safe to have multiple threads reading from the same instance of List<T> only if there are no writers.

Thread Safety

Public static (Shared in Visual Basic) members of this type are thread safe. Any instance members are not guaranteed to be thread safe.

It is safe to perform multiple read operations on a List, but issues can occur if the collection is modified while it’s being read. To ensure thread safety, lock the collection during a read or write operation. To enable a collection to be accessed by multiple threads for reading and writing, you must implement your own synchronization. For collections with built-in synchronization, see the classes in the System.Collections.Concurrent namespace. For an inherently thread–safe alternative, see the ImmutableList class.

Emphasis is mine.

http://msdn.microsoft.com/en-us/library/6sh2ey19(v=vs.110).aspx

Upvotes: 6

Related Questions