There are some cases where I really like using Guava's Striped class.
Is there an equivalent in C#?
It doesn't look like there is a direct equivalent, but there are some lockless thread-safe collection options (I'm not sure what you're trying to achieve, so I can't say if they will work for your scenario). Have a look at the System.Collections.Concurrent Namespace.
In particular, ConcurrentBag, ConcurrentQueue, ConcurrentStack, and ConcurrentDictionary all have different locking/lockless thread-safe strategies. Some are explained in this blog post.
You might be able to get what you want via the Partitioner class, although I am unsure of the implementation.
#Behrooz is incorrect in saying that all .net framework types only use a single lock for the entire list. Take a look at the source for ConcurrentDictionary. Line 71 suggests that this class is implemented using multiple locks.
If you really want to, you could write your own version. The source for the Guava Striped is: https://github.com/google/guava/blob/master/guava/src/com/google/common/util/concurrent/Striped.java
I think best you can do is implementing your own because all dotnet framework types offer only one lock for the entire list.
To do that you can use the GetHashCode() function, modulus(%) it with the number of stripes you want. and use it as an index for Tuple<TLock, List<T>>[] where TLock can be any kind of lock defined in System.Threading namespace and T is the type you want to store/access.
With this you can decide how you want your stripes to be stored. There are choices like HashSet(inefficient in your case since you already use some of the bits to calculate the stripe index), SortedSet, List, Array.
btw, Thank you for the question, It's gonna help me solve a problem I'm having.
Have you tried Tamarind from NuGet?
It's C# port of Google's Guava library
I think the ConcurrentDictionary can archive a similar result.
Based on their documentation:
All these operations are atomic and are thread-safe with regards to all other operations on the ConcurrentDictionary class. The only exceptions are the methods that accept a delegate, that is, AddOrUpdate and GetOrAdd. For modifications and write operations to the dictionary, ConcurrentDictionary uses fine-grained locking to ensure thread safety. (Read operations on the dictionary are performed in a lock-free manner.) However, delegates for these methods are called outside the locks to avoid the problems that can arise from executing unknown code under a lock. Therefore, the code executed by these delegates is not subject to the atomicity of the operation.
As you can see, read operations are lock-free. That will allow you to not block the threads from reading while other are inserting for example.
Related
Consider that I have a custom class called Terms and that class contains a number of strings properties. Then I create a fairly large (say 50,000) List<Terms> object. This List<Terms> only needs to be read from but it needs to be read from by multiple instances of Task.Factory.StartNew (the number of instances could vary from 1 to 100s).
How would I best pass that list into the long running task? Memory isn't too much of a concern as this is a custom application for a specific use on a specific server with plenty of memory. Should I reference it or should I just pass it off as a normal argument into the method doing the work?
Since you're passing a reference it doesn't really matter how you pass it, it won't copy the list itself. As Ket Smith said, I would pass it as a parameter to the method you are executing.
The issue is List<T> is not entirely thread-safe. Reads by multiple threads are safe but a write can cause some issues:
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. To ensure thread safety, lock the collection during a read or write operation.
From List<T>
You say your list is read-only so that may be a non-issue, but a single unpredictable change could lead to unexpected behavior and so it's bug-prone.
I recommend using ImmutableList<T> which is inherently thread-safe since it's immutable.
So long as you don't try to copy it into each separate task, it shouldn't make much difference: more a matter of coding style than anything else. Each task will still be working with the same list in memory: just a different reference to the same underlying list.
That said, sheerly as a matter of coding style and maintainability, I'd probably try to pass it in as a parameter to whatever method you're executing in your Task.Factory.StartNew() (or better yet, Task.Run() - see here). That way, you've clearly called out your task's dependencies, and if you decide that you need to get the list from some other place, it's more clear what you've got to change. (But you could probably find 20 places in my own code where I haven't followed that rule: sometimes I go with what's easier for me now than with what's likely to be easier for the me six months from now.)
It looks like the mono implementation has no MemoryBarrier calls inside the ReaderWriterLockSlim methods. So when I make any changes inside a write lock, I can receive old cached values in another thread which uses a read lock.
Is it really possible? Should I insert MemoryBarrier before and after the code inside Read and Write lock?
Looking at (what I think is) the mono source, the Mono ReaderWriterLockSlim is implemented using Interlocked calls.
These calls include a memory barrier on x86, so you shouldn't need to add one.
As Peter correctly points out, the implementation does introduce a memory barrier, just not explicitly.
More generally: the C# language specification requires that certain side effects be well ordered with respect to locks. Though that rule only applies to locks entered with the C# lock statement, it would be exceedingly strange for a provider of a custom locking primitive to make a locking object that did not follow the same rules. You are wise to double-check, but in general you can assume that if its a threading primitive then it has been designed to ensure that important side effects are well-ordered around it.
I am new to multithreading and have a question on sharing objects. I am doing this in C# .Net 4.5
I have an list that contains a object called Price. The class Price contains 12 properties one of type datetime and the others are of type double.
I then run 4 tasks which all reference this object List. None of the tasks will change the List object they are just reading from the object.
So the fact the tasks are all referencing the same object but only reading from it am I right to think that I will not need any locking?
Yes the read does not modify anything for those types (and indeed most types), so it's safe.
Until and unless you do not have update and add going on any other thread you do not need to add locking. If update or edit is going on any other thread then do consider to use locking.
ReaderWriterLockSlim provides an easy and efficient way to provide advanced Reader and Writer locks.
Moreover as mentioned in Thread Safety section in documentation,
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.
How can I send and receive messages between threads?
One solution would be share a concurrent queue, for example (albeit its name) ConcurrentQueue. This will allow you to enqueue an object from one thread and have the other thread (or others threads) dequeue from the queue. As it is a generic solution, you may pass strongly typed items, anything from string to Action will do, or your own custom message class of course.
Threre is just one limitation with this approach, the class ConcurrentQueue is only available from .NET 4.0 onwards. If you need this for a previous version of .NET you need to look for a third party libary. For example you can take the source for ConcurrentQueue from mono.
The general approach over which those queues work is by having a linked list and they resource to optimistic concurrency control using spinning for synchronization. As far as I know, this is the state of art for concurrent queues of variable size. Now, if you know the message load beforehand you can try a fixed size approach or a solution that favors enqueue and dequeue over growing (that would be an array based queue).
Full disclouser (according to faq): I'm the author of one of those third party libraries... my libraries (nuget available), it includes a backport ConcurrentQueue for old versions of .NET, based on a custom implementation. You can find the underlaying structure under Theraot.Collections.ThreadSafe.SafeQueue, it is a linked list of arrays (which are kept in an object pool), by doing it this way, we do not need to copy the arrays to grow (because we just add another node to the list), and we do not need to rely on synchronization mechanisms as often (because adding or removing an item does not modify the list often).
Note: this question used to link to HashBucket, which is hosted on another repository, and was my old solution for the problem. That project is discontinued, please use the version I mention above.
This is an old question, but still a relevant topic...
A producer/consumer approach may be used as possible solution for a problem like this. .NET Core, from version 3.0, has a namespace with tools to deal with that in a simple way.
Take a look at System.Threading.Channels:
https://learn.microsoft.com/en-us/dotnet/api/system.threading.channels
https://devblogs.microsoft.com/dotnet/an-introduction-to-system-threading-channels/
I think you are talking about Joining between threads? and this.
One way to do it is to create a class that has the method that you will call for the thread.
That class can have more than just the method; it can have members that the parent thread can have access to.
Given that, the parent can read from and write to those members, that way there is a means of communication between the two threads throughout the span of the thread's life.
There are many thread synchronization primitives you can use in .Net such as EventWaitHandle, Mutex, Semaphores etc. Here is a useful link on MSDN to find out how. - https://learn.microsoft.com/en-us/dotnet/standard/threading/overview-of-synchronization-primitives
I was wondering if i could safely read from an XmlDocument object using SelectNodes() and SelectSingleNode() from multiple threads with no problems. MSDN says that they are not guaranteed to be thread safe. If SelectNodes() and SelectSingleNode() do present problems running from multiple threads, could i use proper locking to avoid any issues? I have a WCF service set up that needs to grab a chunk of xml from a database and select some info out of this xml. I'd like to cache the xml to avoid hitting the database so often, but i'm concerned about thread safety and performance. Is there a better way to go about doing this? Thanks
Here's the deal. If the documentation says that instance methods are not guarenteed to be threadsafe then you better take note. And if you do decide to use the class in a multithreaded scenario without the proper synchronization mechanisms then you need to be 1) aware the consequences of ignoring the documentation and 2) prepared for all of your assumptions to be invalidated on future versions of the class. This advice is valid even for methods that seem to only be reading internal state.
How do you know that SelectNodes and SelectSingleNodes do not modify an internal variable? Because if they do then they are definitely not threadsafe! Now, I happen to use Reflector to look inside and I can see that they do not modify any internal variables. But, how do you know that would not change in a future version?
Now, since we know in reality that SelectNodes and SelectSingleNodes do not modify the internal state of the class they may be safe for multithreaded operations despite the warning if and only if the following conditions apply.
After the XmlDocument is initialized no other method besides SelectNodes or SelectSingleNode is called...ever. Because I have not examined all methods on the XmlDocument class I cannot say what ones modify the internal state of the class and which ones do not and as a result I would consider all but the 2 methods I just mentioned a possible risk to breaking down your lock free approach to using the class.
An explicit or implicit memory barrier is created after the XmlDocument is initialized on one thread and before SelectNodes or SelectSingleNodes is called on another thread. I should note that a memory barrier will most likely be created implicitly for you as a result of getting the multithreaded environment setup. But, I can think of some subtle scenarios where this breaks down.
My advice...take the warning in the documentation literally and use the appropriate synchronization mechanisms.
As you are going to write/read to/from the XML document you need to synchronize those two operations if you don't want to run into race conditions. And if you care about performance (who doesn't?) a ReaderWriterLockSlim might perform better than locking.
SelectNodes / SelectSingleNode should be safe (they only read data). Of course you need to synchronize those with any method that actually modifies the xml.
you could also use MsXml FreeThreadedDOMDocument model instead of the classical DomDocument when you call createInstance.
Beware that according this article, FreeThreadedDOMDocument is 7x or 10x slower than classical DomDocument.