List<T> Thread Safety

List T thread safety

No! It is not safe at all, because processed.Add is not. You can do following:

items.AsParallel().Select(item => SomeProcessingFunc(item)).ToList();

Keep in mind that Parallel.ForEach was created mostly for imperative operations for each element of sequence. What you do is map: project each value of sequence. That is what Select was created for. AsParallel scales it across threads in most efficient manner.

This code works correctly:

var processed = new List<Guid>();
Parallel.ForEach(items, item =>
{
lock(items.SyncRoot)
processed.Add(SomeProcessingFunc(item));
});

but makes no sense in terms of multithreading. locking at each iteration forces totally sequential execution, bunch of threads will be waiting for single thread.

Thread-safe List T property

If you are targetting .Net 4 there are a few options in System.Collections.Concurrent Namespace

You could use ConcurrentBag<T> in this case instead of List<T>

Is List T thread-safe for reading?

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

final List T and thread safety

The final makes no difference here. The code is not thread-safe, whether the final is there or not.

There are two reasons that this is not thread-safe.

  1. You are publishing (and potentially mutating) the state of Dummy before its constructor has completed. This is unsafe whether or not the variable is final.

  2. You are returning a shared mutable object in the getIntegers() call. So that means that the caller could change it, and a second caller may or may not see the results ... due to lack of synchronization. Once again final makes no difference to this.


The thread-safety guarantees of final are limited. Here's what the JLS says:

final fields also allow programmers to implement thread-safe immutable objects without synchronization. A thread-safe immutable object is seen as immutable by all threads, even if a data race is used to pass references to the immutable object between threads. This can provide safety guarantees against misuse of an immutable class by incorrect or malicious code. final fields must be used correctly to provide a guarantee of immutability.

An object is considered to be completely initialized when its constructor finishes. A thread that can only see a reference to an object after that object has been completely initialized is guaranteed to see the correctly initialized values for that object's final fields.

The takeaways are that the final guarantees only apply to immutable objects, and they only apply after the return of the object's constructor.

In your example does not satisfy either of these prerequisites. Therefore, the guarantees do not apply.

Is this c# usage of List thread safe?

No, it's not thread-safe. You might be looking for the ConcurrentBag<T> class, a thread-safe unordered collection. Some more info and other thread-safe collections are available at MSDN's Thread-Safe Collections documentation. E.g.

static List<int> Calculate(List<string[]> numbers)
{
var sums = new ConcurrentBag<int>();

Parallel.ForEach(numbers,
(nums) =>
{
int sum = 0;
for (int i = 0; i < nums.Length; i++)
sum += Convert.ToInt32( nums[i]);

sums.Add(sum);
});

var sorted = sums.OrderBy(x => x).ToList();
return sorted;
}

Is it safe to add and remove items from a List object?

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.

C# List T indexer thread safety

Have a read here:

https://msdn.microsoft.com/en-us/library/6sh2ey19.aspx#Anchor_10

To answer your question, no - as per the documentation, it's not guaranteed to be thread safe.

Even if the current implementation appeared to be thread safe (which it doesn't, anyway), it would still be a bad idea to make that assumption. Since the documentation explicitly says it's not thread safe - future versions may legally change the underlying implementation to no longer be thread safe and break any assumption you previously relied on.

List.Add() thread safety

Behind the scenes lots of things happen, including reallocating buffers and copying elements. That code will cause danger. Very simply, there are no atomic operations when adding to a list, at the least the "Length" property needs to be updates, and item needs to be put in at the right location, and (if there's a separate variable) the index needs to be updated. Multiple threads can trample over each other. And if a grow is required then there is lots more going on. If something is writing to a list nothing else should be reading or writing to it.

In .NET 4.0 we have concurrent collections, which are handily threadsafe and don't require locks.



Related Topics



Leave a reply



Submit