Reputation: 2761
I have an application that has many threads, where each thread performs some operation on a resource that is referenced by a GUID, where said GUID is stored in a list as strings. Only one operation can occur on the resource referenced by the GUID at any time.
I'm trying to use lock statements for this and a simple List. The problem I'm running into is that I can't seem to safely put the check to see if the list contains the GUID inside a lock statement, and then follow it with another lock statement to add it to the list. It seems that when there are multiple threads, each checking to see if that GUID is in the list, and the check returns false for both, they both add the GUID (obvious problem).
Also, I can't put the check inside the same lock as the statement to add the GUID to the string list, because if I do, the lock will be held, preventing other threads that are working on the resource from removing it from the list (they can't get the lock).
I hope you'll forgive my primitive example, but I can't figure out how to reliably test and lock safely in a multi-threaded environment. I'm not at liberty to change the design of the app for my client, either, unfortunately.
If you have a class/library to recommend, a small example would be most appreciated.
private static readonly object _guidLock = new object();
private static List<string> guidList = new List<string>();
public static bool isGuidLocked(string guid)
{
lock (_guidLock)
{
if (guidList.Contains(guid)) return true;
return false;
}
}
public static bool lockGuid(string guid)
{
while (isGuidLocked(guid)) { }
lock (_guidLock)
{
guidList.Add(guid);
}
return true;
}
public static bool releaseGuid(string guid)
{
lock (_guidLock)
{
guidList.Remove(guid);
}
return true;
}
public static void doWorkOnGuid(string guid)
{
lockGuid(guid);
// do something there
releaseGuid(guid);
}
Upvotes: 1
Views: 763
Reputation: 1
Use time stamp based concurrency control techniques for such situations. Use one static variable _guidListUpdateTime which will hold the latest _guidList modifying time. Similarly, assign a readtime stamp value to each thread. Now while adding the guid to list check whether the current thread readtime stamp is greater than the _guidListUpdateTime or not. If yes, then add the guid to guidList otherwise not. https://www.classle.net/book/timestamp-based-protocol
Upvotes: 0
Reputation: 7909
Don't use a List. .NET provides thread-safe collections.
In this case you probably want ConcurrentDictionary using the GUID as the key.
See namespace: System.Collections.Concurrent
The System.Collections.Concurrent namespace provides several thread-safe collection classes that should be used in place of the corresponding types in the System.Collections and System.Collections.Generic namespaces whenever multiple threads are accessing the collection concurrently.
Upvotes: 4