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. lock
ing 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.
You are publishing (and potentially mutating) the state of
Dummy
before its constructor has completed. This is unsafe whether or not the variable isfinal
.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 againfinal
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
Readonlycollection or Ienumerable for Exposing Member Collections
Purpose of Activator.Createinstance with Example
Why Is .Contains Slow? Most Efficient Way to Get Multiple Entities by Primary Key
How to Show Animated Gifs on a Windows Form (C#)
Quick and Simple Hash Code Combinations
How to Wait for a Backgroundworker to Cancel
Apply Properties Values from One Object to Another of the Same Type Automatically
Entity Framework - Code First - Can't Store List<String>
What's the Difference Between Ienumerable and Array, Ilist and List
Addbusinessdays and Getbusinessdays
Embedding Assemblies Inside Another Assembly
Extracting Mantissa and Exponent from Double in C#
Strip the Byte Order Mark from String in C#
Sort Observablecollection<String> Through C#