可以锁定System.Collections.Generic.List <t>?</t>

时间:2009-11-14 18:06:33

标签: c#

我一直在阅读有关syncroot元素但我无法在List类型中找到它。 那么如何使用System.Collections.Generic.List&lt;&gt;进行多线程同步呢?类型?

4 个答案:

答案 0 :(得分:11)

为什么要锁定List<T>而不是列表的特定实例?

通常建议锁定的最佳方法是锁定专门为此目的创建的私有对象。

private readonly object myListLock = new object();

// Everywhere you access myList
lock(myListLock)
{
 // do stuff with myList
}

有关使用C#进行线程化的精彩指南,请参阅Joe Albahari的Free E-Book (Threading in C#)

答案 1 :(得分:11)

你无法找到它的原因是因为它是explicitly removed。如果它确实是您想要做的,请使用SynchronizedCollection<T>或创建专用同步对象。最好的方法(一般)是创建一个专用的同步对象,如Winston所示。

SyncRoot属性的基本问题是它提供了一种错误的安全感 - 它只处理一组非常狭窄的情况。假设SyncRoot上的锁定足够好,开发人员通常会忽略整个逻辑操作的同步。

您通常希望避免锁定类型(在这种情况下为List<T>)。例如,如果您有两个类型的实例,或者另一个类型也使用List<T>上的锁,那么它们都将竞争单个全局锁。实际上,您要实现的是单个对象的正确同步。

答案 2 :(得分:7)

您必须将通用列表转换为ICollection,如下所示:

using System.Collection; // required for ICollection
using System.Collection.Generic;
List<int> myIntList = new List<int>();
lock (((ICollection)myIntList).SyncRoot)
{
    // do your synchronized stuff here...
}

请记住,这只会同步访问通用列表的元素。它 同步对通用列表变量的访问权限,例如myIntList。如果您在某个时候用新列表替换myIntList,则使用SyncRoot是不够的。在这种情况下,我建议创建一个可用于两种同步方案的特定同步对象。

答案 3 :(得分:2)

答案是肯定的,您可以使用列表实例作为同步对象:

{{1}}

因此,您不必使用SyncRoot属性。此外,documentation表示

  

对于底层商店不公开的集合,   预期的实现是返回当前实例。

即。在某些情况下,SyncRoot属性会返回集合对象本身。

另请阅读this answer有关SyncRoot的信息。

仅供参考:我从未在生产代码中看到过SyncRoot的用法。所以我建议你使用任何集合的实例作为同步对象而不是它的SyncRoot属性(只要集合是私有的)。