Multithreading 处理多线程服务上的并发问题
我正在设计一个web服务(wcf),它有一些静态字典(即维护服务器和连接的客户端的一些状态)。该服务处于单实例模式和多并发模式,如下所示Multithreading 处理多线程服务上的并发问题,multithreading,wcf,concurrency,locking,deadlock,Multithreading,Wcf,Concurrency,Locking,Deadlock,我正在设计一个web服务(wcf),它有一些静态字典(即维护服务器和连接的客户端的一些状态)。该服务处于单实例模式和多并发模式,如下所示 [ServiceBehavior(InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode=ConcurrencyMode.Multiple)] public class CalculatorService : ICalculatorConcurrency {
[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();
...
}
}
}
[服务行为(InstanceContextMode=InstanceContextMode.Single,ConcurrencyMode=ConcurrencyMode.Multiple)]
公共类计算器服务:iCalculator并发
{
私有静态int-clientId;
私有静态对象lockObject=新对象();
私有静态字典numberList=新字典();
公共静态编号ReadNumber(整数n)
{
号码信息;
锁定(锁定对象)
{
如果(!numberList.TryGetValue(n,输出信息))
...
}
}
公共静态bool修改(编号)
{
锁定(锁定对象)
{
...
}
}
公共图书馆
{
锁定(锁定对象)
{
numberList.Clear();
...
}
}
}
我的代码是线程安全的吗?或者,我做得对吗?因为您只使用一个资源(即
lockObject
),所以死锁是不可能的。要获得死锁,您需要至少有两个资源
我的代码是线程安全的吗
如果您使用Dictionary
来避免任何并发问题,那么与该Dictionary的每次交互都应该像您所做的那样由lock(lockObject){}
包装。因此,您的代码是线程安全的
我做得对吗
您的操作是正确的,但如果您使用的是.Net 4
或最新版本,则使用线程安全选项会更方便。它是专为您这样的情况而设计的。不同之处在于,您可以忘记lock
块。当一个调用程序遍历字典,而第二个调用程序更改字典时,它不会引发异常ConcurrentDictionary
实现了IDictionary
,此外,还提供了方便的方法,如TryAddd
、TryUpdate
和其他方法
因此,如果可能的话,您肯定需要使用
ConcurrentDictionary
,因为它使代码更干净。因为您只使用一个资源(即lockObject
),死锁是不可能的。要获得死锁,您需要至少有两个资源
我的代码是线程安全的吗
如果您使用Dictionary
来避免任何并发问题,那么与该Dictionary的每次交互都应该像您所做的那样由lock(lockObject){}
包装。因此,您的代码是线程安全的
我做得对吗
您的操作是正确的,但如果您使用的是.Net 4
或最新版本,则使用线程安全选项会更方便。它是专为您这样的情况而设计的。不同之处在于,您可以忘记lock
块。当一个调用程序遍历字典,而第二个调用程序更改字典时,它不会引发异常ConcurrentDictionary
实现了IDictionary
,此外,还提供了方便的方法,如TryAddd
、TryUpdate
和其他方法
因此,如果可能的话,您肯定需要使用
ConcurrentDictionary
,因为它使代码更干净。您运行过吗?发生了什么事?@jsanalytics正在按预期运行,但我不确定这是否足以解决可能出现的死锁?另外,如果我对每个方法使用不同的锁对象,因为我没有注意到结果中的任何变化,这有区别吗?您是否运行了一个场景,其中多个任务同时对您的服务进行多个调用?@jsanalytics我不太熟悉如何从实际服务中调试这些并发问题,因此,希望您能提供一些见解,我将非常感谢。对于我的测试,我从不同的测试应用程序调用了相同的服务:控制台应用程序和桌面应用程序。您运行它吗?发生了什么事?@jsanalytics正在按预期运行,但我不确定这是否足以解决可能出现的死锁?另外,如果我对每个方法使用不同的锁对象,因为我没有注意到结果中的任何变化,这有区别吗?您是否运行了一个场景,其中多个任务同时对您的服务进行多个调用?@jsanalytics我不太熟悉如何从实际服务中调试这些并发问题,因此,希望您能提供一些见解,我将非常感谢。对于我的测试,我从不同的测试应用程序中调用了相同的服务:控制台应用程序和桌面应用程序,以获取您的回复和其他见解。我将探讨并发类型感谢您的回复和其他见解。我将探讨并发类型