Are C# Arrays Thread Safe

Are C# arrays thread safe?

I believe that if each thread only works on a separate part of the array, all will be well. If you're going to share data (i. e. communicate it between threads) then you'll need some sort of memory barrier to avoid memory model issues.

I believe that if you spawn a bunch of threads, each of which populates its own section of the array, then wait for all of those threads to finish using Thread.Join, that that will do enough in terms of barriers for you to be safe. I don't have any supporting documentation for that at the moment, mind you ...

EDIT: Your sample code is safe. At no time are two threads accessing the same element - it's as if they each have separate variables. However, that doesn't tend to be useful on its own. At some point normally the threads will want to share state - one thread will want to read what another has written. Otherwise there's no point in them writing into a shared array instead of into their own private variables. That's the point at which you need to be careful - the coordination between threads.

Array and Safe Access by Threads

When two threads are accessing the exact same resource (e.g., not local copies, but actually the same copy of the same resource), a number of things can happen. In the most obvious scenario, if Thread #1 is accessing a resource and Thread #2 changes it mid-read, some unpredictable behavior can happen. Even with something as simple as an integer, you could have logic errors arise, so try to imagine the horrors that can result from improperly using something more complicated, like a database access class that's declared as static.

The classical way of handling this problem is to put a lock on the sensitive resources so only one thread can use it at a time. So in the above example, Thread #1 would request a lock to a resource and be granted it, then go in to read what it needs to read. Thread #2 would come along mid-read and request a lock to the resource, but be denied and told to wait because Thread #1 is using it. When Thread #1 finishes, it releases the lock and it's OK for Thread #2 to proceed.

There are other situations, but this illustrates one of the most basic problems and solutions. In C#, you may:

1) Use specific .NET objects that are managed as lockable by the framework (like Scorpion-Prince's link to SynchronizedCollection)

2) Use [MethodImpl(MethodImplOptions.Synchronized)] to dictate that a specific method that does something dangerous should only be used by one thread at a time

3) Use the lock statement to isolate specific lines of code that are doing something potentially dangerous

What approach is best is really up to your situation.

Thread safety in C# arrays

This particular case is safe, yes.

Reading and writing to different parts of an array does not interfere with the other operations.

However, reading and writing to the same location can give you problems, depending on the type of element, and the size of the elements.

Is Array.Resize(..) threadsafe?

  • The method will not alter the original array.
  • The method will not throw an exception in multi-threaded scenarios that it would not throw in single-threaded scenarios, because the source array has a fixed size and the elements are not being dereferenced.
  • The method is thread-safe if the new length is equal to the old length, because according to the documentation the method does nothing in that case.
  • If the source array is modified during the operation, the contents of the resized array are unspecified. If the elements of the array fit into a machine word (IntPtr.Size or smaller, including reference types), the elements of the resulting array will each either contain the value of the same element in the source array when the method was invoked, or any value that was assigned to that element during the execution of the resize operation. If the elements do not fit into a machine word, then any element which is modified during the execution of the resize operation will result in an unspecified value for the corresponding element in the resized array.

Is iterating over an array with a for loop a thread safe operation in C# ? What about iterating an IEnumerable T with a foreach loop?

Is iterating over an array with a for loop a thread safe operation in C# ?

If you're strictly talking about reading from multiple threads, that will be thread safe for Array and List<T> and just about every collection written by Microsoft, regardless of if you're using a for or foreach loop. Especially in the example you have:

var temp = new List<int>();

foreach (var name in Names)
{
temp.Add(name.Length * 2);
}

You can do that across as many threads as you want. They'll all read the same values from Names happily.

If you write to it from another thread (this wasn't your question, but it's worth noting)

Iterating over an Array or List<T> with a for loop, it'll just keep reading, and it'll happily read the changed values as you come across them.

Iterating with a foreach loop, then it depends on the implementation. If a value in an Array changes part way through a foreach loop, it will just keep enumerating and give you the changed values.

With List<T>, it depends what you consider "thread safe". If you are more concerned with reading accurate data, then it kind of is "safe" since it will throw an exception mid-enumeration and tell you that the collection changed. But if you consider throwing an exception to be not safe, then it's not safe.

But it's worth noting that this is a design decision in List<T>, there is code that explicitly looks for changes and throws an exception. Design decisions brings us to the next point:

Can we assume that every collection that implements IEnumerable is safe to read across multiple threads?

In most cases it will be, but thread-safe reading is not guaranteed. The reason is because every IEnumerable requires an implementation of IEnumerator, which decides how to traverse the items in the collection. And just like any class, you can do anything you want in there, including non-thread-safe things like:

  • Using static variables
  • Using a shared cache for reading values
  • Not making any effort to handle cases where the collection changes mid-enumeration
  • etc.

You could even do something weird like make GetEnumerator() return the same instance of your enumerator every time its called. That could really make for some unpredictable results.

I consider something to not be thread safe if it can result in unpredictable results. Any of those things could cause unpredictable results.

You can see the source code for the Enumerator that List<T> uses, so you can see that it doesn't do any of that weird stuff, which tells you that enumerating List<T> from multiple threads is safe.

Array Pointer thread safety

Writing the address of a new pointer is an atomic operation:

5.5 Atomicity of variable references

Reads and writes of the following data types are atomic: bool, char, byte, sbyte, short, ushort, uint, int, float, and reference types. In addition, reads and writes of enum types with an underlying type in the previous list are also atomic. Reads and writes of other types, including long, ulong, double, and decimal, as well as user-defined types, are not guaranteed to be atomic.

Since an array pointer is a reference, it is thread safe.

In order to avoid cache side-effects, you can use the volatile keyword as well.


However you must be very carefull with this. Say you have a method:

public class Foo {

private volatile int[] data;

public void Method () {
for(int i = 0; i < data.length; i++) {
data[i] = i;
}
}

public void OtherMethod (int[] data) {
this.data = data;
}

}

Say you set the data array to an array with a different length, it is possible that the for-loop checks the length fetches the length of the old array, then the reference is modified to a shorter array and then you access an illegal index.

Non-blocking multithreaded applications, therefore make a copy of the reference to the array, modify the array and then check if the reference is modified.

C# - thread-safe implementation of a class with fixed array (queue/buffer?) (ADD, REMOVE, MODIFY)

Since you are new to multithreading, the answer about what you should do is simple: lock every time you access a shared resource. "Access" means read and write. "Shared resource" means every variable or field or property that is accessed by more than one threads concurrently. Use the same lock object to protect the same variable. Release the lock as soon as possible.

This advice is not enough for creating a performant application, nor is enough for avoiding deadlocks, but at least your data will not be corrupted.

Is ArrayPool T .Rent(Int32) Method thread-safe?

Update Comment from ta.speot.is

It literally says on
Thread safety This
class is thread-safe. All members may be used by multiple threads
concurrently

Original

It doesn't say it on learn.microsoft.com, however there is a few references to the fact it is

Add a new System.Buffers namespace to the BCL for Resource Pooling

The Pool will be lightweight and thread-safe, allowing for fast Rent
and Return calls from any thread within the process, along with
minimal locking overhead, and 0 heap allocations on most Rent calls
(exceptions to this will be called out below in the description of the
Rent function).

Pooling large arrays with ArrayPool

Recommended: use the ArrayPool.Shared property, which returns a
shared pool instance. It’s thread safe and all you need to remember is
that it has a default max array length, equal to 2^20 (1024*1024 = 1
048 576).

.



Related Topics



Leave a reply



Submit