提高并发字典访问效率c#

End*_*ace 1 c# concurrency locking list c#-4.0

我有一个列表,由多个后台线程访问以进行更新/读取.更新操作包括插入和删除.

为了在没有同步问题的情况下同时执行此操作,我在类中使用了一个私有只读对象的锁.

为了最大限度地减少我在读取数据时需要锁定列表的时间,我会对其进行深度克隆并返回深度克隆并解锁字典以进行插入/删除更新.

因此,每次读取列表都会增加我的服务的内存消耗.

需要注意的一点是,插入/删除是包含列表的类的内部.但阅读是为了公共消费.

我的问题是:

有什么办法,我可以避免克隆列表并仍然使用它同时使用读/写锁读取?

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();
                }
            }
        }
    }
Run Code Online (Sandbox Code Playgroud)

Tej*_*ejs 6

听起来您需要使用ConcurrentDictionary该类,并为Users您正在存储的每个对象创建一个键.然后,就像添加/更新用户一样简单:

_dictionary.AddOrUpdate("key", (k, v) =>
    {
        return newUser;
    }, (k, v) =>
    {
        return newUser;
    });
Run Code Online (Sandbox Code Playgroud)

然后删除,你会这样做:

 Users value = null;
_dictionary.TryRemove("key", out value);
Run Code Online (Sandbox Code Playgroud)

获取人员列表也非常简单,因为您只需要这样做:

return _dictionary.Values.Select(x => x.Value).ToList();
Run Code Online (Sandbox Code Playgroud)

哪个应该在那个时刻返回字典内容的副本.

让.NET运行时为您处理线程.


SLa*_*aks 5

您可以使用读写器锁定以允许同时读取.

但是,使用ConcurrentDictionary和线程安全的不可变值会更快,然后摆脱所有同步.