Is ArrayPool<T>.Rent(Int32) Method thread-safe? - c#

I just found out about ArrayPool existence, but it's documentation is somewhat lacking.
I'd like to know if Rent(.) and Return(.) are thread-safe.
Edit: looks like I didn't notice the "Thread Safety" part of documentation; but reading some of the comments and answers I was relieved I wasn't the only one that didn't.

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

it's documentation is somewhat lacking.
You can read about thread safety under Thread Safety:
Thread Safety
This class is thread-safe. All members may be used by multiple threads concurrently.

Related

C# variable thread safety

A few questions about accessing a local variable from multiple threads at once:
I have multiple threads writing and reading the value of a variable, should i synchronize access to it or not?
The variable is being updated every few seconds from Thread1 and its being read and updated to the Database every few seconds from Thread2.
Which problems can occur if i don't hold any logic and don't have any concurrency issues?
Should i use volatile for this?
EDIT:
I would like to emphasize that i don't have any concurrency issues. Here's my specific scenarion:
a. My variable's name is pingLatency and it measures ping latency
b. Thread1 is sending a ping to 8.8.8.8 each 10 seconds and writes the latency to pingLatency
c. Thread2 updates a correcposing field with the value of pingLatency each 10 seconds.
d. Thread2 updates the same database row each time.
Now, i'm using this database field to monitor network connectivity. My question is - Can there be a situation where the variable is not updated or it would throw an exception due to thread safety issues? I want to avoid using lock because it just seems like an overkill.
What do you think?
Yes you should synchronize access to it, if it is a primitive type there are methods to do this for you without locks
no comment
not sure by what you mean by this... most likely you'll end up inserting the wrong value into the DB
Don't use volatile, per Eric Lippert, it's overly complicated and the semantics are very weird.
Be careful of breaking the memory model, C# by and large follows most other languages in using sequential consistency for data-race-free programs (SC-DRF). Volatile breaks this, so just use locks to prevent a data race.
As for lock it's not as heavy as one might imagine, in most cases the lock won't be contended in the scenario you imagine. So acquiring the lock should be painless in most cases.
If you want .NET managed parallelism use the built in good stuff. Task Parallelism. This will manage the threads for you and you can use the thread safe variables that are built in just as an array/list would be equal to ConcurrentBag, etc.
If access to your variable is atomic and there are no logical problems you are OK.
according to this you can know if you are using an atomic variable.

Is it possible to cause a deadlock when using thread-safe .NET 4+ collections?

Are the collections in System.Collections.Concurrent fully thread-safe in all cases? Or is it theoretically possible to cause a deadlock when using multiple concurrent collections from multiple threads?
Thanks.
Well, some of the types can certainly be used in ways that cause deadlocks. For example, BlockingCollection.Take blocks until an element is available, so if you call this on the UI thread and some background thread that the produces items for the Take winds up having to synchronize something through the UI thread (say there's a COM dependency that marshals silently in the background), you can deadlock. As always when dealing with threading, a reasonable level of paranoia is recommended, even when using 'thread safe' classes.
The classes are (for the most part) thread safe, as documented on MSDN. For example, the documentation for ConcurrentQueue<T> explicitly states:
All public and protected members of ConcurrentQueue are thread-safe and may be used concurrently from multiple threads.
All required synchronization is handled internally.
Also note that some types have some minor thread safety issues, such as BlockingCollection<T>.Dispose(), which is not thread safe, but again documented on MSDN:
The Dispose method is not thread-safe. All other public and protected members of BlockingCollection are thread-safe and may be used concurrently from multiple threads.
That being said, if you're doing your own synchronization, you may be causing dead locks unrelated to the usage of these types. If you're experiencing dead locks, it's most likely due to some other synchronization in your code or a library you're using.

Is it safe for multiple threads to read from a Lookup<TKey, TElement>?

Is it safe for multiple threads to read from a Lookup<TKey, TElement>?
Lookup<TKey, TElement> is immutable, however MSDN states:
Any public static (Shared in Visual Basic) members of this type are
thread safe. Any instance members are not guaranteed to be thread
safe.
Though I shudder to imagine it, I'm wondering if the machine that pumps out MSDN documentation
could be incorrect.
Because I don't like to risk that I may have to debug an obscure multithreading related bug 1 year from now, I'm going to assume it's not safe to use this class without manual synchronization.
As long as there is no writing, doing just reading is thread-safe. This is valid in any case.
Your question is in a sense orthogonal to the notion of thread-safety. A write in combination with a write or read is not thread-safe, but multiple reads without writing are thread-safe.
What MSDN says about instance members not being guaranteed to be thread-safe can only be valid in case of non-thread-safe scenarios, which by definition imply a write operation.
This is standard disclaimer for all most classes as you've probably noticed. Some methods may be thread safe, but "are not guaranteed".
Generally it is safe to read from collection using multiple threads if there are no writers to collection. If you need to update collection at the same time - use appropriate synchronization or built in thread safe collections like SynchronizedKeyedCollection.
Because the Lookup<TKey,TElement> is immutable, means that you will get the same values for all members. It does not mean that the items stored in it cannot be modified. So the collection is indeed not thread safe. A perfect example would be that most linq is lazy evaluated, and creating the enumerator could involve executing the lazy code. Trying to enumerate in two separate threads could cause the collection to be realized twice producing the wrong result.
Update:
Now that the source code is available on https://referencesource.microsoft.com it is confirmed that internal state is set during method calls without regard to multithreading meaning that you could have race conditions and the Lookup<TKey,TElement> class is in fact not thread safe.

What is the meant by 'thread safe' object?

I have used generic queue in C# collection and everyone says that it is better to use the object of System.Collection.Generic.Queue because of thread safety.
Please advise on the right decision to use Queue object, and how it is thread safe?
"Thread safe" is a bit of an unfortunate term because it doesn't really have a solid definition. Basically it means that certain operations on the object are guaranteed to behave sensibly when the object is being operated on via multiple threads.
Consider the simplest example: a counter. Suppose you have two threads that are incrementing a counter. If the sequence of events goes:
Thread one reads from counter, gets
zero.
Thread two reads from counter, gets
zero.
Thread one increments zero, writes
one to counter.
Thread two increments zero, writes
one to counter.
Then notice how the counter has "lost" one of the increments. Simple increment operations on counters are not threadsafe; to make them threadsafe you can use locks, or InterlockedIncrement.
Similarly with queues. Not-threadsafe-queues can "lose" enqueues the same way that not-threadsafe counters can lose increments. Worse, not threadsafe queues can even crash or produce crazy results if you use them in a multi-threaded scenario improperly.
The difficulty with "thread safe" is that it is not clearly defined. Does it simply mean "will not crash"? Does it mean that sensible results will be produced? For example, suppose you have a "threadsafe" collection. Is this code correct?
if (!collection.IsEmpty) Console.WriteLine(collection[0]);
No. Even if the collection is "threadsafe", that doesn't mean that this code is correct; another thread could have made the collection empty after the check but before the writeline and therefore this code could crash, even if the object is allegedly "threadsafe". Actually determining that every relevant combination of operations is threadsafe is an extremely difficult problem.
Now to come to your actual situation: anyone who is telling you "you should use the Queue class, it is better because it is threadsafe" probably does not have a clear idea of what they're talking about. First off, Queue is not threadsafe. Second, whether Queue is threadsafe or not is completely irrelevant if you are only using the object on a single thread! If you have a collection that is going to be accessed on multiple threads, then, as I indicated in my example above, you have an extremely difficult problem to solve, regardless of whether the collection itself is "threadsafe". You have to determine that every combination of operations you perform on the collection is also threadsafe. This is a very difficult problem, and if it is one you face, then you should use the services of an expert on this difficult topic.
A type that is thread safe can be safely accessed from multiple threads without concern for concurrency. This usually means that the type is read-only.
Interestingly enough, Queue<T> is not thread safe - it can support concurrent reads as long as the queue isn't modified but that isn't the same thing as thread safety.
In order to think about thread safety consider what would happen if two threads were accessing a Queue<T> and a third thread came along and began either adding to or removing from this Queue<T>. Since this type does not restrict this behavior it is not thread safe.
In dealing with multithreading, you usually have to deal with concurrency issues. The term "concurrency issues" refers to issues that are specifically introduced by the possibility of interleaving instructions from two different execution contexts on a resource shared by both. Here, in terms of thread safety, the execution contexts are two threads within a process; however, in related subjects they might be processes.
Thread safety measures are put in place to achieve two goals primarily. First is to regain determinism with regard to what happens if the threads context-switch (which is otherwise controlled by the OS and thus basically nondeterministic in user-level programs), to prevent certain tasks from being left half-finished or two contexts writing to the same location in memory one after the other. Most measures simply use a little bit of hardware-supported test-and-set instructions and the like, as well as software-level synchronization constructs to force all other execution contexts to stay away from a data type while another one is doing work that should not be interrupted.
Usually, objects that are read-only are thread-safe. Many objects that are not read-only are able to have data accesses (read-only) occur with multiple threads without issue, if the object is not modified in the middle. But this is not thread safety. Thread safety is when all manner of things are done to a data type to prevent any modifications to it by one thread from causing data corruption or deadlock even when dealing with many concurrent reads and writes.

When should each thread synchronization objects be used?

Under what circumstances should each of the following synchronization objects be used?
ReaderWriter lock
Semaphore
Mutex
Since wait() will return once for each time post() is called, semaphores are a basic producer-consumer model - the simplest form of inter-thread message except maybe signals. They are used so one thread can tell another thread that something has happened that it's interested in (and how many times), and for managing access to resources which can have at most a fixed finite number of users. They offer ordering guarantees needed for multi-threaded code.
Mutexes do what they say on the tin - "mutual exclusion". They ensure that the right to access some resource is "held" by only on thread at a time. This gives guarantees of atomicity and ordering needed for multi-threaded code. On most OSes, they also offer reasonably sophisticated waiter behaviour, in particular to avoid priority inversion.
Note that a semaphore can easily be used to implement mutual exclusion, but that because a semaphore does not have an "owner thread", you don't get priority inversion avoidance with semaphores. So they are not suitable for all uses which require a "lock".
ReaderWriter locks are an optimisation over mutexes, in cases where you will have a lot of contention, most accesses are read-only, and simultaneous reads are permissible for the data structure being protected. In such cases, exclusion is required only when a writer is involved - readers don't need to be excluded from each other. To promote a reader to writer all other readers must finish (or abort and start waiting to retry if they also wish to become writers) before the writer lock is acquired. ReaderWriter locks are likely to be slower in cases where they aren't faster, due to the additional book-keeping they do over mutexes.
Condition variables are for allowing threads to wait on certain facts or combinations of facts being true, where the condition in question is more complex than just "it has been poked" as for semaphores, or "nobody else is using it" for mutexes and the writer part of reader-writer locks, or "no writers are using it" for the reader part of reader-writer locks. They are also used where the triggering condition is different for different waiting threads, but depends on some or all of the same state (memory locations or whatever).
Spin locks are for when you will be waiting a very short period of time (like a few cycles) on one processor or core, while another core (or piece of hardware such as an I/O bus) simultaneously does some work that you care about. In some cases they give a performance enhancement over other primitives such as semaphores or interrupts, but must be used with extreme care (since lock-free algorithms are difficult in modern memory models) and only when proven necessary (since bright ideas to avoid system primitives are often premature optimisation).
Btw, these answers aren't C# specific (hence for example the comment about "most OSes"). Richard makes the excellent point that in C# you should be using plain old locks where appropriate. I believe Monitors are a mutex/condition variable pair rolled into one object.
I would say each of them can be "the best" - depends on the use case ;-)
Simple answer: almost never.
The best type of locking is to not need a lock (no shared mutable state).
If you do need a lock, try and use a Monitor (via a lock statement), unless you have specific needs for something different (in which case see Onebyone's answer
Additionally, prefer ReaderWriteLockSlim to ReaderWriterLock (except in the extremely rare case of requiring the latter's fairness).

Categories

Resources