37

Is the following pseudocode thread-safe ?

IList<T> dataList = SomeNhibernateRepository.GetData();

Parallel.For(..i..)
{
    foreach(var item in dataList)
    {
       DoSomething(item);
    }
}

The list never gets changed, it's only iterated and read in parallel. No writing to fields or something like that whatsoever.

Thanks.

user315648
  • 1,945
  • 3
  • 22
  • 30

4 Answers4

60

Yes, List<T> is fine to read from multiple threads concurrently, so long as nothing's writing.

From the documentation:

A List<T> can support multiple readers concurrently, as long as the collection is not modified.

EDIT: Note that your code doesn't necessarily use List<T> - just an IList<T>. Do you know the type returned by GetData()? If you're in control of GetData() you probably want to document that the list returned by it is thread-safe for reading, if it's actually returning a List<T>.

Theodor Zoulias
  • 34,835
  • 7
  • 69
  • 104
Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • What about calling find() on an instance variable List from within a singleton method? Could the results possibly get returned to the wrong user? – eaglei22 May 02 '19 at 17:52
  • @eaglei22: I'm afraid I don't know what you mean - I suggest you ask a new question with much more context. But fundamentally I doubt that it would just be `Find` that's a problem - if you've got multiple threads modifying a single `List` without protection, that's fundamentally a problem. – Jon Skeet May 02 '19 at 18:10
  • Thanks Jon. Sorry for the confusion. If two users access a method within a singleton class: GetCode(string code) => return conditionCodes.Find(x => x.Code.Equals(code)); the List object "conditionCodes" only get populated never changed. Is concurrent access safe? I will will add a new question if this is still confusing. Thank you. – eaglei22 May 02 '19 at 18:24
  • 1
    @eaglei22: Yes, that's a case of multiple readers with no modification, so it should be fine. – Jon Skeet May 02 '19 at 18:25
3

It's fully thread-safe as long as DoSomething(item) doesn't modify dataList. Since you said it doesn't, then yes, that is thread-safe.

jakobbotsch
  • 6,167
  • 4
  • 26
  • 39
2

To make sure no one is going to change your list, you could access it through an IEnumerable

IEnumerable<T> dataList = SomeNhibernateRepository.GetData();

Parallel.For(..i..)
{
    foreach(var item in dataList)
    {
       DoSomething(item);
    }
}
Mangesh
  • 5,491
  • 5
  • 48
  • 71
Massimiliano Peluso
  • 26,379
  • 6
  • 61
  • 70
  • That could still be cast back to a List. You could return List.AsReadOnly(), but even so the original list is accessible with reflection. – jakobbotsch Aug 05 '11 at 12:01
  • 2
    if you cast back the List you still can't modify the original list If you are considering the reflection you could circumvent runtime checks as well . how can you make a field private? you may anwer with the private keywork. I may answer you with the reflection I can access it. – Massimiliano Peluso Aug 05 '11 at 12:15
-1

If whay you say is correct then I would say so. But what you say or think may not what happen in reality. How can you say in code what you have said. How to enforce the constraint that List is never modified?

Brett Walker
  • 3,566
  • 1
  • 18
  • 36
  • 3
    That's relatively easy: make it a private member in a class which only performs read access to the list, possibly exposing the values via other members. The class needs to be kept under control, but it's a single piece of code to look at. – Jon Skeet Aug 05 '11 at 11:58