【发布时间】:2016-05-27 21:04:05
【问题描述】:
我正在使用一种接收列表的方法来更新字典。此列表包含应该存储在字典中的更新值。例如:我的字典中存储了值 1,2,3,4。一个线程尝试使用列表 0、1、3、5 更新字典中的值。我在该线程中的“刷新”方法需要从字典中删除 2,4,并添加 0,5。
我将有多个线程尝试快速连续地执行此“刷新”,因此我想确保它们的操作不会重叠并弄乱字典。因此,我需要每个尝试更新字典以完成其操作的线程,然后再移动到下一个线程。我还需要确保字典按照线程尝试更新的顺序进行更新。
在我当前的代码中,一个线程创建一个新列表,然后调用 Refresh() 来更新 SubscriptionCache 中的字典。在创建新列表之前,我让每个线程休眠 3-8 毫秒,然后使用新列表刷新字典。
看看我的代码:
public static class SubscriptionCache
{
private static ConcurrentDictionary<int, Subscription> _firstPartySubscriptionIds = new ConcurrentDictionary<int, Subscription>();
//This compares the contents of the dictionary and new list,
then updates the dictionary accordingly.
internal static void Refresh(IEnumerable<Subscription> firstPartySubscriptionIds)
{
lock(_firstPartySubscriptionIds)
{
try
{
Compare(firstPartySubscriptionIds, true).ForEach((s) =>
{
var t = _firstPartySubscriptionIds.TryAdd(s.GetHashCode(), s); Print("Added" + s.SystemID + " Success: " + t + " With Key: " + s.GetHashCode());
});
Compare(firstPartySubscriptionIds, false).ForEach((s) =>
{
var t = _firstPartySubscriptionIds.TryRemove(s.GetHashCode(), out s); Print("Removed" + s.SystemID + "Success: " + t + " With key: " + s.GetHashCode());
});
LastRefreshedOn = DateTime.Now;
}
catch { }
}
}
private static List<Subscription> Compare(IEnumerable<Subscription> firstPartySubscriptionIds, bool reverse)
{
var masterList = _firstPartySubscriptionIds.Values.ToList();
var newList = firstPartySubscriptionIds.ToList();
var returnList = new List<Subscription>();
if (reverse == false) // Returns elements in the old list which are NOT in the new list
{
foreach (Subscription s in masterList)
{
if (!newList.Contains(s))
{
returnList.Add(s);
}
}
}
else //Returns elements in the new list which are NOT in the old list
{
foreach (Subscription s in newList)
{
if (!masterList.Contains(s))
{
returnList.Add(s);
}
}
}
return returnList;
}
【问题讨论】:
-
您确定简单的锁定会给您带来性能问题吗?
-
你需要检查你的代码。
-
@Evk 现在我正在考虑它,我不明白没有它我的程序将如何工作。我想不出另一种可以在概念上起作用的方式。
-
好吧,如果这是一个问题,问题也是如此。看来您的代码在该潜在锁定内没有执行任何繁重的操作(例如,不调用外部服务\数据库) - 所以无论如何锁定都没有问题。
-
@Evk 在 Refresh() 中锁定整个代码块后,我仍然遇到问题。这应该确保一次只有一个线程可以添加到字典中,但我确实需要线程按照它们创建的顺序添加到字典中。
标签: c# multithreading concurrentdictionary