I have a list that is accessed by multiple background threads to update/read. Updates actions include both insertions and deletions.
To do this concurrently without synchronization problems, I am using a lock on a private readonly object in the class.
To minimize the time I need to lock the list when reading its data, I do a deep clone of it and return the deep clone and unlock the dictionary for insert/delete updates.
Due to this every read of the list increases the memory consumption of my service.
One point to note is that the inserts/deletes are internal to the class that contains the list. But the read is meant for public consumption.
My question is:
Is there any way, I can avoid cloning the list and still use it concurrently for reads using read/write locks?
public class ServiceCache
{
private static List<Users> activeUsers;
private static readonly object lockObject = new object();
private static ServiceCache instance = new ServiceCache();
public static ServiceCache Instance
{
get
{
return instance;
}
}
private void AddUser(User newUser)
{
lock (lockObject)
{
//... add user logic
}
}
private void RemoveUser(User currentUser)
{
lock (lockObject)
{
//... remove user logic
}
}
public List<Users> ActiveUsers
{
get
{
lock (lockObject)
{
//The cache returns deep copies of the users it holds, not links to the actual data.
return activeUsers.Select(au => au.DeepCopy()).ToList();
}
}
}
}
It sounds like you need to use the
ConcurrentDictionaryclass, and create a key for each of theUsersobjects you are storing. Then it becomes as simple as this for adding / updating a user:And then for removing, you would do this:
Getting the list of people would be super easy as well, since you would just need to do:
Which should return a copy of the dictionary contents at that very moment.
And let the .NET runtime take care of the threading for you.