Threading and iterating through changing collections - multithreading

In C# (console app) I want to hold a collection of objects. All objects are of same type.
I want to iterate through the collection calling a method on each object. And then repeat the process continuously.
However during iteration objects can be added or removed from the list. (The objects themselves will not be destroyed .. just removed from the list).
Not sure what would happen with a foreach loop .. or other similar method.
This has to have been done 1000 times before .. can you recommend a solid approach?

There is also copy based approach.
The algorithm is like that:
take the lock on shared collection
copy all items from shared collection to some local collection
release lock on shared collection
Iterate over items in local collection
The advantage of this approach is that you take the lock on shared collection for small period of time (assuming that shared collection is relatively small).
In case when method that you want to invoke on every collection item takes some considerable time to complete or can block then the approach of iterating under shared lock can lead to blocking other threads that want to add/remove items from shared collection
However if that method that you want to invoke on every object is relatively fast then iterating under shared lock can be more preferable.

This is classic case of syncronization in multithreading.
Only solid approach and better approach would be syncronization between looping and addition/deletion of items from list.
Means you should allow addition/deletion only at end of end and start of iterating loop!
some thing like this:-
ENTER SYNC_BLOCK
WAIT FOR SYNC_BLOCK to be available
LOOP for items/ call method on them.
LEAVE SYNC_BLOCK
ENTER SYNC_BLOCK
WAIT FOR SYNC_BLOCK to be available
Add/Delete items
LEAVE SYNC_BLOCK

What comes to mind when I read this example is that you could use a C5 TreeSet/TreeBag. It does require that there be a way to order your items, but the advantage of the Tree collections is that they offer a Snapshot method (A member of C5.IPersistentSorted) that allows you to make light-weight snapshots of the state of the collection without needing to make a full duplicate.
e.g.:
using(var copy = mySet.Snapshot()) {
foreach(var item in copy) {
item.DoSomething();
}
}
C5 also offers a simple way to "apply to all" and is compatible with .NET 2.0:
using(var copy = mySet.Snapshot()) {
copy.Apply(i => i.DoSomething());
}
It's important to note that the snapshot should be disposed or you will incur a small performance penalty on subsequent modifications to the base collection.
This example is from the very thorough C5 Book.

Related

What multithreading based data structure should I use?

I have recently come across a question based on multi-threading. I was given a situation where there will be variable no of cars constantly changing there locations. Also there are multiple users who are posting requests to get location of any car at any moment. What would be data structure to handle this situation and why?
You could use a mutex (one per car).
Lock: before changing location of the associated car
Unlock: after changing location of the associated car
Lock: before getting location of the associated car
Unlock: after done doing work that relies on that location being up to date
I'd answer with:
Try to make threading an external concept to your system yet make the system as modular and encapsulated as possible at the same time. It will allow adding concurrency at later phase at low cost and in case the solution happens to work nicely in a single thread (say by making it event-loop-based) no time will have been burnt for nothing.
There are several ways to do this. Which way you choose depends a lot on the number of cars, the frequency of updates and position requests, the expected response time, and how accurate (up to date) you want the position reports to be.
The easiest way to handle this is with a simple mutex (lock) that allows only one thread at a time to access the data structure. Assuming you're using a dictionary or hash map, your code would look something like this:
Map Cars = new Map(...)
Mutex CarsMutex = new Mutex(...)
Location GetLocation(carKey)
{
acquire mutex
result = Cars[carKey].Location
release mutex
return result
}
You'd do that for Add, Remove, Update, etc. Any method that reads or updates the data structure would require that you acquire the mutex.
If the number of queries far outweighs the number of updates, then you can do better with a reader/writer lock instead of a mutex. With an RW lock, you can have an unlimited number of readers, OR you can have a single writer. With that, querying the data would be:
acquire reader lock
result = Cars[carKey].Location
release reader lock
return result
And Add, Update, and Remove would be:
acquire writer lock
do update
release writer lock
Many runtime libraries have a concurrent dictionary data structure already built in. .NET, for example, has ConcurrentDictionary. With those, you don't have to worry about explicitly synchronizing access with a Mutex or RW lock; the data structure handles synchronization for you, either with a technique similar to that shown above, or by implementing lock-free algorithms.
As mentioned in comments, a relational database can handle this type of thing quite easily and can scale to a very large number of requests. Modern relational databases, properly constructed and with sufficient hardware, are surprisingly fast and can handle huge amounts of data with very high throughput.
There are other, more involved, methods that can increase throughput in some situations depending on what you're trying to optimize. For example, if you're willing to have some latency in reported position, then you could have position requests served from a list that's updated once per minute (or once every five minutes). So position requests are fulfilled immediately with no lock required from a static copy of the list that's updated once per minute. Updates are queued and once per minute a new list is created by applying the updates to the old list, and the new list is made available for requests.
There are many different ways to solve your problem.

LMAX Disruptor: Must EventHandler clone object received from EventHandler#onEvent

I have an application with Many Producers and consumers.
From my understanding, RingBuffer creates objects at start of RingBuffer init and you then copy object when you publish in Ring and get them from it in EventHandler.
My application LogHandler buffers received events in a List to send it in Batch mode further once the list has reached a certain size. So EventHandler#onEvent puts the received object in the list , once it has reached the size , it sends it in RMI to a server and clears it.
My question, is do I need to clone the object before I put in list, as I understand, once consumed they can be reused ?
Do I need to synchronize access to the list in my EventHandler#onEvent ?
Yes - your understanding is correct. You copy your values in and out of the ringbuffer slots.
I would suggest that yes you clone the values as you extract it from the ring buffer and into your event handler list; otherwise the slot can be reused.
You should not need to synchronise access to the list as long as it is a private member variable of your Event Handler and you only have one event handler instance per thread. If you have multiple event handlers adding to the same (eg static) List instance then you would need synchronisation.
Clarification:
Be sure to read the background in OzgurH's comments below. If you stick to using the endOfBatch flag on disruptor and use that to decide the size of your batch, you do not have to copy objects out of the list. If you are using your own accumulation strategy (such as size - as per the question), then you should clone objects out as the slot could be reused before you have had the chance to send.
Also worth noting that if you are needing to synchronize on the list instance, then you have missed a big opportunity with disruptor and will destroy your performance anyway.
It is possible to use slots in the Disruptor's RingBuffer (including ones containing a List) without cloning/copying values. This may be a preferable solution for you depending on whether you are worried about garbage creation, and whether you actually need to be concerned about concurrent updates to the objects being placed in the RingBuffer. If all the objects being placed in the slot's list are immutable, or if they are only being updated/read by a single thread at a time (a precondition which the Disruptor is often used to enforce), there will be nothing gained from cloning them as they are already immune to data races.
On the subject of batching, note that the Disruptor framework itself provides a mechanism for taking items from the RingBuffer in batches in your EventHandler threads. This is approach is fully thread-safe and lock-free, and could yield better performance by making your memory access patterns more predictable to the CPU.

thread safe search-and-add

I need to be able to do the following:
search a linked list.
add a new node to the list in case it's not found.
be thread safe and use rwlock since it's read mostly list.
The issue i'm having is when I promote from read_lock to write_lock I need to search the list again just to make sure some other thread wasn't waiting on a write_lock while I was doing the list search holding the read_lock.
Is there a different way to achieve the above without doing a double list search (perhaps a seq_lock of some sort)?
Convert the linked list to a sorted linked list. When its time to add a new node you can check again to see if another writer has added an equivalent node while you were acquiring the lock by inspecting only two nodes, instead of searching the entire list. You will spend a little more time on each node insertion because you need to determine the sorted order of the new node, but you will save time by not having to search the entire list. Overall you will probably save a lot of time.

Thread locking / exclusive access improvements

I have 2 threaded methods running in 2 separate places but sharing access at the same time to a list array object (lets call it PriceArray), the first thread Adds and Removes items from PriceArray when necessary (the content of the array gets updated from a third party data provider) and the average update rate is between 0.5 and 1 second.
The second thread only reads -for now- the content of the array every 3 seconds using a foreach loop (takes most items but not all of them).
To ensure avoiding the nasty Collection was modified; enumeration operation may not execute exception when the second thread loops through the array I have wrapped the add and remove operation in the first thread with lock(PriceArray) to ensure exclusive access and prevent that exception from occurring. The problem is I have noticed a performance issue when the second method tries to loop through the array items as most of the time the array is locked by the add/remove thread.
Having the scenario running this way, do you have any suggestions how to improve the performance using other thread-safety/exclusive access tactics in C# 4.0?
Thanks.
Yes, there are many alternatives.
The best/easiest would be to switch to using an appropriate collection in System.Collections.Concurrent. These are all thread-safe collections, and will allow you to use them without managing your own locks. They are typically either lock-free or use very fine grained locking, so will likely dramatically improve the performance impacts you're getting from the synchronization.
Another option would be to use ReaderWriterLockSlim to allow your readers to not block each other. Since a third party library is writing this array, this may be a more appropriate solution. It would allow you to completely block during writing, but the readers would not need to block each other during reads.
My suggestion is that ArrayList.Remove() takes most of the time, because in order to perform deletion it performs two costly things:
linear search: just takes elements one by one and compares with element being removed
when index of the element being removed is found - it shifts everything below it by one position to the left.
Thus every deletion takes time proportionally to count of elements currently in the collection.
So you should try to replace ArrayList with more appropriate structure for this task. I need more information about your case to suggest which one to choose.

Populating a ListView in a multithreaded app

I need to retrieve a set of data from a database, then populate a ListView with the data. I understand multithreaded form controls and the proper techniques for updating controls from worker threads. Here's the dilemma:
I may have several thousand entries in the ListView... rather than Invoking the form thread to update them one at a time, I'd like to build a collection of ListViewItem objects and use ListView.Items.AddRange(ListViewItemCollection).
However, the MSDN documentation advises not to create your own ListViewItemCollection (and indeed, trying to create my own ListViewItemCollection generates a null reference error because there's no parent set). Instead, MS recommends that you only work with a ListViewItemCollection by getting it via the ListView.Items property.
Which, of course, is circular reasoning and can't be done from a worker thread without generating an error: "Cross-thread operation not valid: Control 'ListView' accessed from a thread other than the thread it was created on."
I could use the overloaded AddRange(ListViewItem[]), but arrays are rather clunky in this day and age.
Anyone have a suggestion how to add several thousand items to a ListView from a worker thread?
I think you already have your answer - AddRange(ListViewItem[]). If you find arrays distasteful, you can use a List and then do a toArray() right when you call AddRange.

Resources