【发布时间】:2019-05-01 06:45:41
【问题描述】:
我在 IIS 应用程序池中有 WCF 服务。 WCF 服务的方法接收一些 JSON 格式的数据,例如 {"object": "someobject", "payload": [int key]}。
对于每个请求,我都会运行新线程来处理密钥。
键正在添加到 ConcurrentDictionary 并锁定 ConcurrentDictionary 的值。
这样做的目的是:一次只能运行一个 key 示例,例如:
Thread 1-Running with key 1
Thread 2-使用 键 2
线程 3运行-等待锁定线程 1
但是当我从 ConcurrentDictionary 中删除键时,另一个线程已经通过键获取值并使用它。如何避免这种情况?
附近的线程处理程序示例
static ConcurrentDictionary<string, object> taskDictionary=new ConcurrentDictionary<string, object>();
static void ThreadHandler(int key)
{
try
{
var lockElem=taskDictionary.GetOrAdd(key, new object());
//Thread 3 get value by key 1 here and waits here
lock(lockElem)
{
taskDictionary.TryRemove(key, out _);
// but Thread 1 removes value by key 1 here
//and Thread 4 can add value in Dictionary with same key (key 1)
}
}
finally
{
}
}
问题就在这种情况下:线程 1 使用 GetOrAdd,然后是锁定值,然后是 TryRemove。此时线程 3. 使用 GetOrAdd,取值,但等待线程 1 的锁。当线程 1 的锁释放时,线程 3 的锁移除值。此时线程 4 使用 GetOrAdd,并创建新的字典元素(与线程 3 获取的值不匹配)。我们有 2 个线程(线程 3 和线程 4)使用相同的键。
【问题讨论】:
-
这更多的是关于你的解决方案(算法)而不是线程安全。您可以使用锁内的 ContainsKey 解决第一个问题。但是,当可以重新添加密钥时,您必须在此处更好地指定逻辑。
-
@HenkHolterman 如何检查锁内的值与键不存在?当键移除时,另一个线程(例如线程 4)在字典中添加新值
-
嗯,你有字典,你有钥匙......你可以使用
!。 -
对不起,我不明白
-
我已经回答了。
标签: c# multithreading thread-safety concurrentdictionary