我正在设计一个具有某些静态词典的Web服务(wcf)(即,维护服务器和连接的客户端的某些状态)。该服务处于单实例模式和多并发状态,如下所示。
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode=ConcurrencyMode.Multiple)]
public class CalculatorService : ICalculatorConcurrency
{
...
}
有多种操作可以读取和写入此静态变量。我有一个类级别的锁定对象,每当任何操作尝试访问该特定静态变量时,我试图避免使用锁定的方法就是使用该对象。
我是否正确处理了并发,如下所示?客户端可以访问服务的各种实例,即
示例代码如下:
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode=ConcurrencyMode.Multiple)]
public class CalculatorService : ICalculatorConcurrency
{
private static int clientId;
private static object lockObject = new object();
private static Dictionary<int, Number> numberList = new Dictionary<int, Number>();
public static Number ReadNumber(int n)
{
Number info;
lock (lockObject)
{
if (!numberList.TryGetValue(n, out info))
...
}
}
public static bool Modify(Number number)
{
lock (lockObject)
{
...
}
}
public bool Clear()
{
lock (lockObject)
{
numberList.Clear();
...
}
}
}
我的代码线程安全吗?或者,此外,我做得正确吗?
答案 0 :(得分:2)
由于您仅使用一种资源(即lockObject
),因此不可能发生死锁。要陷入僵局,您至少需要两个资源。
我的代码线程安全吗?
如果您使用Dictionary<,>
来避免任何并发问题,则与该字典的每次交互都应像以前一样由lock(lockObject){}
包装。因此,您的代码是线程安全的。
我做对了吗?
您的操作正确,但是如果使用的是.Net 4
或最新的版本,则可以使用线程安全的ConcurrentDictionary<TKey,TValue>
来获得更方便的选择。它专门针对像您这样的情况而设计。区别在于您可以忘记lock
个块。当一个调用者遍历字典而第二个调用者更改字典时,它不会引发异常。 ConcurrentDictionary<TKey,TValue>
实现了IDictionary<TKey,TValue>
,此外,还提供了方便的方法,例如TryAdd
,TryUpdate
等。
因此,如果可能的话,您绝对需要使用ConcurrentDictionary
,因为它会使代码更简洁。