Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is the List<T>.AddRange() thread safe?

Can I, without locking, safely call List.AddRange(r) from multiple threads? If not, what sort of trouble would I run into?

like image 817
Erik Forbes Avatar asked Oct 28 '10 14:10

Erik Forbes


2 Answers

No, its documentation does not say it is thread safe, therefore it is not.

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

As to what can go wrong, think about what AddRange(newItems) does:

  • Check if there is enough space in the internal array
  • If not:
    • Allocate a new array
    • Copy the current items to the new array
    • Set a field to point at the new array
  • Copy the newItems to the correct local in the internal array
  • Update the “count” field (this is used to control where the next item is inserted)

Now think what will happen if the above is mixed up with another call to AddRange() or even just a call to read an item.

like image 180
Ian Ringrose Avatar answered Sep 19 '22 17:09

Ian Ringrose


No it's not, but I'd like to add it's more efficient to do an myList.AddRange(...); within a lock than doing several lock (syncLock) { myList.Add(...) };.

Which sort of trouble would you run into? When one thread is adding an item while another is enumerating the list, List<T> will throw a certain exception because it does some internal versioning, as it wants to prevent us poor developers from hitting nasty side effects.

Also the List<T> internally keeps an array in which it stores its items. Maybe setting an item in an array is pretty atomic, but whenever the capacity of this array is reached, a new one will be created and the items will be copied over from the old one. So when a thread wants to add something while that copying takes place, you can imagine that things would go out of sync.

like image 27
herzmeister Avatar answered Sep 17 '22 17:09

herzmeister