How to effectively maintain locks at the item and collection level?

I have an application that has a set of domain objects that need to be updated in real time. Multiple threads can take actions that modify items in this collection and should do so safely. The current approach is simplified, making essentially a global lock before making any changes. More or less something like the following:

private readonly object lockObject = new object(); private Dictionary<int, Widget> items; private void UpdateAllWidgets() { lock (this.lockObject) { // Update all the widgets. No widgets should be permitted to be // updated while this is running. } } private void UpdateWidget(int widgetId) { lock (this.lockObject) { // Update the widget with id = widgetId. I want to me able to // update other widgets at the same time, however. } } 

Now I'm having performance issues because the lock is too rough. I would like to be able to use locks at the item level while one item (while allowing other items to be updated at the same time), but still be able to take a collection level lock if necessary. Thus, the behavior will look like this: the following:

 Thread 1: UpdateWidget(1); Thread 2: UpdateWidget(2); // This can run before UpdateWidget(1) // completes. Thread 1: UpdateWidget(1); Thread 2: UpdateAllWidgets(); // This has to wait for UpdateWidget(1) Thread 3: UpdateWidget(2); // This has to wait for UpdateAllWidgets() Thread 4: UpdateWidget(3); // This has to wait for UpdateAllWidgets(), but // not UpdateWidget(2) 

Any ideas on the lock structure that would support this? . The example above requires a simplified version, but we have already excluded ConcurrentDictionary not enough. Actions taken, for example, UpdateWidget, are not just simple updates in place. These may include database updates that affect this item, etc.

+5
source share
1 answer

I would prefer my answer to the assumption that you have compared this multithreaded behavior and divided all the work into one thread. If not, please, you may find that it is much faster to avoid a lock conflict.

What you are looking for is a writer blocker, possibly ReaderWriterLockSlim in .net. To update a single item, take a read lock , then lock() item, upgrade and release lock() , and then read the lock. To perform an β€œall items” update, add or remove a record lock that will be exclusive.

+3
source

Source: https://habr.com/ru/post/1258941/


All Articles