Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

IEnumerable<T> thread safety?

I have a main thread that populates a List<T>. Further I create a chain of objects that will execute on different threads, requiring access to the List. The original list will never be written to after it's generated. My thought was to pass the list as IEnumerable<T> to the objects executing on other threads, mainly for the reason of not allowing those implementing those objects to write to the list by mistake. In other words if the original list is guaranteed not be written to, is it safe for multiple threads to use .Where or foreach on the IEnumerable?

I am not sure if the iterator in itself is thread safe if the original collection is never changed.

like image 483
e36M3 Avatar asked May 12 '11 13:05

e36M3


People also ask

Are enumerators thread-safe?

Creation of Enum instance is thread-safeBy default, the Enum instance is thread-safe, and you don't need to worry about double-checked locking. In summary, the Singleton pattern is the best way to create Singleton in Java 5 world, given the Serialization and thread-safety guaranteed and with some line of code enum.

Is Linq thread-safe?

They're not thread safe.

Is yield return thread-safe?

As written it is thread safe but if you comment out the lock(_sync) in AllValues you should be able to verify that it is not thread safe by running it a few times.

Are enums thread-safe C#?

Well by default, enum is of type int, 32bit, unless explicitly specified otherwise. That means, that reading/writing is atomic => thread-safe.


2 Answers

IEnumerable<T> can't be modified. So what can be non thread safe with it? (If you don't modify the actual List<T>).

For non thread safety you need writing and reading operations.

"Iterator in itself" is instantiated for each foreach.

Edit: I simplified my answer a bit, but @Eric Lippert added valuable comment. IEnumerable<T> doesn't define modifying methods, but it doesn't mean that access operators are thread safe (GetEnumerator, MoveNext and etc.) Simplest example: GetEnumerator implemented as this:

  • Every time returns same instance of IEnumerator
  • Resets it's position

More sophisticated example is caching.

This is interesting point, but fortunately I don't know any standard class that has not thread-safe implementation of IEnumerable.

like image 180
Andrey Avatar answered Sep 20 '22 19:09

Andrey


Each thread that calls Where or foreach gets its own enumerator - they don't share one enumerator object for the same list. So since the List isn't being modified, and since each thread is working with its own copy of an enumerator, there should be no thread safety issues.

You can see this at work in one thread - Just create a List of 10 objects, and get two enumerators from that List. Use one enumerator to enumerate through 5 items, and use the other to enumerate through 5 items. You will see that both enumerators enumerated through only the first 5 items, and that the second one did not start where the first enumerator left off.

like image 22
Phil Avatar answered Sep 23 '22 19:09

Phil