2

Assume we have multiple threads and a public List that is responsible to hold real-time data. We have some thread that is responsible to add data to list object. Another thread is responsible to get data from list object and then remove the items from top.

Question: Is it safe to remove from begin of a List and simultaneously add data to end of list in separate threads? How List object is implemented?

Theodor Zoulias
  • 34,835
  • 7
  • 69
  • 104
HOPE
  • 152
  • 10
  • You can use lock. See: https://stackoverflow.com/questions/1362995/properly-locking-a-listt-in-multithreaded-scenarios – Selim Yildiz Apr 01 '20 at 07:41
  • 1
    No it's not tread safe, base on what you want to implement checkout concurrent collections, especially `ConcurrentQueue` https://learn.microsoft.com/en-us/dotnet/api/system.collections.concurrent.concurrentqueue-1?view=netframework-4.8 – Irdis Apr 01 '20 at 07:45
  • @SelimYıldız I mean is it implemented in list object or we have to it handy? – HOPE Apr 01 '20 at 07:53
  • 1
    Related: [List thread safety](https://stackoverflow.com/questions/5020486/listt-thread-safety) – Theodor Zoulias Apr 01 '20 at 07:55

2 Answers2

5

As from the docs:

Public static 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.

So, if your collection can be modified by some of the threads - you need to lock it on write and read operations.

The docs also points you to another solution:

For collections with built-in synchronization, see the classes in the System.Collections.Concurrent namespace.

Like ConcurrentQueue, for example. Use .Enqueue(obj) to insert it at the end of the queue and TryDequeue(out obj) to get it from the top of the queue.

Community
  • 1
  • 1
vasily.sib
  • 3,871
  • 2
  • 23
  • 26
  • Thanks. Does Dequeue remove completely from ConcurrentQueue and reduce the size of object? – HOPE Apr 01 '20 at 07:55
  • 1
    "So, if you lock your collection while you remove elements from it - you are ok." This is a bit misleading. The lock has to be used when accessing the list independent what the threads do. If you use a read write lock you could be more efficient, but the reading threads still need a lock too – Voo Apr 01 '20 at 08:00
  • 1
    @HOPE, yes, `TryDequeue` removes element from queue. There is also a `TryPeek`, which just "peek" an element from top without removal. – vasily.sib Apr 01 '20 at 08:03
  • 1
    @Voo, agreed. I rephrased this to be less misleading. – vasily.sib Apr 01 '20 at 08:09
  • Thanks. IProducerConsumerCollection is a good choose. I've use it now :) . – HOPE Apr 01 '20 at 10:17
3

List is not thread safe.

The problem you're solving looks like a producer-consumer problem, so what you need is a collection which implements IProducerConsumerCollection<T>:

If you also need bounded buffer (only allow certain amount of items in the collection at all time), you could use BlockingCollection<T>, with any of the above as inner collection.

weichch
  • 9,306
  • 1
  • 13
  • 25