处理多线程服务上的并发问题

时间:2019-02-07 11:25:24

标签: multithreading wcf concurrency locking deadlock

我正在设计一个具有某些静态词典的Web服务(wcf)(即,维护服务器和连接的客户端的某些状态)。该服务处于单实例模式和多并发状态,如下所示。

[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode=ConcurrencyMode.Multiple)]   
public class CalculatorService : ICalculatorConcurrency   
{   
    ...  
}  

有多种操作可以读取和写入此静态变量。我有一个类级别的锁定对象,每当任何操作尝试访问该特定静态变量时,我试图避免使用锁定的方法就是使用该对象。

我是否正确处理了并发,如下所示?客户端可以访问服务的各种实例,即

  • Client1使用服务来修改()字典
  • Client2使用该服务来清除()字典
  • Client3使用服务读取()字典

示例代码如下:

[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();
            ...
        }               
    }
}

我的代码线程安全吗?或者,此外,我做得正确吗?

1 个答案:

答案 0 :(得分:2)

由于您仅使用一种资源(即lockObject),因此不可能发生死锁。要陷入僵局,您至少需要两个资源。

  

我的代码线程安全吗?

如果您使用Dictionary<,>来避免任何并发问题,则与该字典的每次交互都应像以前一样由lock(lockObject){}包装。因此,您的代码是线程安全的。

  

我做对了吗?

您的操作正确,但是如果使用的是.Net 4或最新的版本,则可以使用线程安全的ConcurrentDictionary<TKey,TValue>来获得更方便的选择。它专门针对像您这样的情况而设计。区别在于您可以忘记lock个块。当一个调用者遍历字典而第二个调用者更改字典时,它不会引发异常。 ConcurrentDictionary<TKey,TValue>实现了IDictionary<TKey,TValue>,此外,还提供了方便的方法,例如TryAddTryUpdate等。

因此,如果可能的话,您绝对需要使用ConcurrentDictionary,因为它会使代码更简洁。