Am I right in saying that I only need to use lock to Add/Remove/Change the List, or do I also need to lock it when iterating over it?
So am I thread safe by doing this:
class ItemsList
{
List<int> items = new List<int>();
object listLock = new object();
public void Add(int item)
{
lock (listLock)
{
items.Add(item);
}
}
public void Remove(int item)
{
lock (listLock)
{
items.Remove(item);
}
}
public void IncrementAll()
{
foreach (var item in items)
{
item += 1;
}
}
}
You should definitely lock when iterating over it too – if the list is changed while you’re iterating over it, an exception will be thrown.
From the docs for
List<T>.GetEnumerator:Additionally, even a single read from a
List<T>isn’t thread-safe if you could be writing to it as well – even if it doesn’t fail, there’s no guarantee that you’ll get the most recent value.Basically,
List<T>is only safe for multiple threads if it’s not written to after the last point at which its state becomes visible to all threads.If you want a thread-safe collection, and if you’re using .NET 4 or higher, take a look at the
System.Collections.Concurrentnamespace.