What is the best strategy to lock on varying (dynamic) number of objects/keys?
Consider the scenario, where a thread can only proceed with a task (transaction), when locks are gained on a number of objects (array of objects is dynamic and cannot be predicted). In this example, an ID can represent an Object, which needs to be modified as part of "transaction".
Example:
Thread: Objects to Lock (as part of transaction)
T1: A B C D
T2: B D
T3: A D
EDIT: Improving the example
Clearly, doing sequential dynamic locking, can cause a deadlock for all threads, as T1 can gain lock of A, while T2 gains lock on B, and T3 grabbed lock on D. T1 waits for T2 to release B, and T2 waits for T3 to release D, and T3 waits for T1 to release A.
What are possible options to implement such multi-object locking?
The question is in part theoretical, and in part practical as it must be solved in C# / .NET
Possible Solution:
In order to keep both the parallelism and also maintain correct locking, I thought of the following scheme:
Two Queues:
- Sequential Queue (served by 1 thread only, hence sequential)
- Parallel Queue (served by a pool of threads)
When a request arrives for N objects, examine each object Id and if increment lock count for each ID (this can be a Dictionary<int, int> - <Id, Lock Count>).
IF all IDs are "locked" (note that no actual locking takes place), i.e. requested for the first time, put the request in Parallel queue ELSE put the request in sequential queue
This hybrid approach allows to process "contesting" requests sequentially, and non-contesting - in parallel.