多线程Web服务访问和修改List对象不是线程安全的

本文关键字:线程 安全 对象 List 服务 Web 访问 修改 多线程 | 更新日期: 2023-09-27 18:06:34

当我的多线程应用程序修改同一个对象,而List对象无法处理两个线程同时向列表添加对象时,我经历了一段艰难的经历。

我做了一些研究,发现我可以使用锁来避免这种情况的发生,在应用程序平稳运行一个月后,即使有锁对象,这种情况也会再次发生。我不明白这辆静止的出租车是怎么发生的。错误消息与以前相同:1-源数组不够长。检查srcIndex和长度,以及数组的下限。2-索引超出了数组的界限。

在类私人成员中,我有这个成员变量

private static readonly object _syncLock = new object();

在公共功能中

public Dictionary<int, QueuedLetter> GetXMLFragment(Dictionary<int, QueuedLetter> queuedLetters, GroupNode GroupNode, GroupNode ParentGroupNode, StoredProcedure storedProcedure)

这是我使用_synclock对象的地方,代码行如下所示

XmlFragment xf = new XmlFragment();
xf.Fragment = xe;
xf.LetterQueueOID = lq.LetterQueueOID;
xf.ParentGroupNodeName = ParentGroupNodeName;
xf.LinkingField = GroupNode.LinkingField;
xf.GroupNodeName = GroupNode.GroupNodeName;
lock (_syncLock)
{
   if (lq.Fragments == null)
      lq.Fragments = new List<XmlFragment>();
   lq.Fragments.Add(xf);
}

我使用线程池在另一个类中创建多线程功能,它在上发生锁定的同一类中调用启动函数

events[i] = new AutoResetEvent(false);
AttachFragments f = new AttachFragments(events[i], groupNodeOID, QueuedLetters, string.Format("Failed while fragment Data : {0}, was executing ", groupNodeName));
f.OnException += ThreadErroredOut;
ThreadPool.QueueUserWorkItem(new WaitCallback(f.UpdateFragments));

如果你能就我做错了什么给我一些建议,我将不胜感激。

我已经考虑过使用.NET 4.0中的线程安全集合http://msdn.microsoft.com/en-us/library/dd997305.aspx但我还没有使用过它,如果我把它改成这样,这将导致代码发生巨大变化,这将需要由are Q.a.团队进行更深入的测试。

两个异常的堆栈跟踪:1-源数组不够长。检查srcIndex和长度,以及数组的下限。:在System.Collections.Generic.List 1.Insert(Int32 index, T item) at JE.ThunderHead.Business.AttachFragments.GetXMLFragment(Dictionary处的System.Array.Copy(Array sourceArray,Int32 sourceIndex,Array destinationArray,Int32-destinationIndex,Int32-length,布尔可靠(2个queuedLetters,GroupNode GroupNode,GroupNode ParentGroupNode,StoredProcedurestoredProcedure(在C:''TFS''LMS''Release''LM_05''LM_05.01''Solutions''ThunderHead''JE.TThunderhead.Business''AttachFragments.cs:line 135 at JE.TThuderHead.Business.AttachFractions.UpdateFragments(Object stateinfo(在C:''TFS''LMS''Release ''LM_05/LM_05.01''rSolutions''ThuunderHead''JE.tThunderhead.Business''AAttachFragments.cs:line 99 中

2-索引超出了数组的界限:位于System.Collections.Generic.List 1.Add(T item) at JE.ThunderHead.Business.AttachFragments.GetXMLFragment(Dictionary 2 2 queuedLetters,GroupNode GroupNode,GroupNode ParentGroupNode,StoredProcedurestoredProcedure(,位于C:''TFS''LMS''Release ''LM_05''LM_05.01''Solutions''ThunderHead''JE.TThunderhead.Business''AttachFragments.cs:line 231

从您发布的堆栈跟踪中,该列表上似乎有一个Insert,但您没有在此处显示。如果是这种情况,您还需要使用相同的锁定对象来锁定Insert

多线程Web服务访问和修改List对象不是线程安全的

我可以肯定地说,您显示的代码片段不会同时更新lq

然而,如果没有更多的代码,我就无法告诉你更多。无论lq是什么类,最好都将其子类化,并将锁定放在该实现中。在那之后,我可以肯定地告诉你lq是线程安全的。

我认为您应该考虑重构以使用您建议的ConcurrentQueue<T>。尽管Q.A.循环的成本很高,但您将获得联锁操作和纺纱的质量保证和潜在性能改进。