【发布时间】:2016-05-28 04:37:03
【问题描述】:
到目前为止,我一直在 C# 库中开发static class,所有方法显然都是静态的。任何被操作的数据都会被传入,所以这是线程安全的。但是,我正在实现一个功能,该功能需要 Dictionary 来统计某些字符串 ID,这些 ID 将为每个线程生成不同的值。显然使用类似下面的东西不会是线程安全的,因为多个线程会使用相同的Dictionary 并搞乱它的状态:
private static readonly Dictionary<string, uint> MyTallies = new Dictionary<string, uint>();
那么,让这个线程安全的最佳选择是什么?在我看来,有 3 个(有点糟糕)选项:
- 使类非静态;每个线程都必须创建一个新实例,并且可以为每个线程创建一个新的
Dictionary。性能受到影响。 - 使用
Dictionary在代码周围加上lock,并清除锁定末尾的Dictionary。性能大受打击。 - 将
Dictionary传递给每个需要它的方法。然而,这会导致Dictionary被传入只是用于大多数时间不会使用的可选功能,因此调用代码必须做的事情似乎很奇怪。由于调用代码每次都必须创建Dictionary实例,因此性能也会受到影响。
那么我最好的选择是什么,或者还有其他更好的选择吗?
编辑:一个简单的用例:
internal static class HtmlFormatter {
private static readonly Dictionary<string, uint> MyTallies = new Dictionary<string, uint>();
internal static string RenderHtml(string markdown) {
string outputHtml = "";
// (process markdown and render to HTML)
// (found a heading that requires a unique ID)
var id = generatedId;
string unique = "";
if (MyTallies.ContainsKey(id)) {
// Already exists; suffix "-x" where x is count of duplicate IDs
unique = "-" + ++MyTallies[id];
}
else {
MyTallies[id] = 0;
}
id += unique;
// (append id string to HTML output and continue processing)
return outputHtml;
}
}
【问题讨论】:
-
ConcurrentDictionary? -
@EldarDordzhiev 只有退化边缘情况下的解决方案 - 任何不完全微不足道的事情都不会适用于该解决方案,并且需要代码级锁定。
-
不太确定用例是什么。你提到的选项意味着字典并不是一直都需要的。您能否展示一个示例用法,即谁负责清除字典,它是如何填充和使用的。
标签: c# .net multithreading dictionary