我的理解是,如果您在C#中使用通用列表(List),它可以支持多个并发读取器,但只能支持一个编写器。当您在混合中引入编写器时,还必须提供同步构造以使操作线程安全。
List.Contains是否被视为读取操作?换句话说,如果我调用此方法,我是否需要担心作者可能同时写入此列表?
答案 0 :(得分:23)
是的,你应该。基本上我会同步任何操作,如果列表可能同时用于写入。
通常我发现集合分为两类 - 一类是创建的,初始化的,然后再也没有改变过(线程安全的),另一类是随时间变化的(不是线程安全的,锁定所有访问)。
答案 1 :(得分:4)
如果您使用Reflector检查代码,则可以得到如下内容:
public bool Contains(T item)
{
if (item == null)
{
for (int j = 0; j < this._size; j++)
{
if (this._items[j] == null)
{
return true;
}
}
return false;
}
EqualityComparer<T> comparer = EqualityComparer<T>.Default;
for (int i = 0; i < this._size; i++)
{
if (comparer.Equals(this._items[i], item))
{
return true;
}
}
return false;
}
正如您所看到的,它是对项目的简单迭代,这绝对是一种“读取”操作。如果您仅将其用于读取(并且没有任何改变项目),则无需锁定。如果您开始在单独的线程中修改列表,那么您最需要同步访问。
答案 2 :(得分:2)
List<T>.Contains
肯定是一个读取操作。其他一些线程可能会在您阅读时写入集合。
答案 3 :(得分:2)
是的,你一定要担心! List.Contains只获取一个EqualityComparer,然后循环遍历列表包含的所有项目,将作为参数传递的项目与当前迭代索引处的项目进行比较,因此如果列表在迭代时被修改,结果可能是不可预测的。
答案 4 :(得分:1)
答案 5 :(得分:1)
可以安全地假设这不是线程安全操作。 MSDN description总结了它:
...此方法使用集合 对象的Equals和CompareTo方法 在项目上确定是否项目 存在。
因此,在读取操作之后是比较操作。
答案 6 :(得分:1)
在多线程环境中,您需要确保不会同时写入集合。这是来自反射器的代码,该集合本身并没有为你提供任何锁定,所以它就在你的胜利上。
public bool Contains(T item)
{
if (item == null)
{
for (int j = 0; j < this._size; j++)
{
if (this._items[j] == null)
{
return true;
}
}
return false;
}
EqualityComparer<T> comparer = EqualityComparer<T>.Default;
for (int i = 0; i < this._size; i++)
{
if (comparer.Equals(this._items[i], item))
{
return true;
}
}
return false;
}
答案 7 :(得分:0)
如果作者可能同时写作,List.Contains肯定不是线程安全的。你需要用锁来包装它和任何其他的读写。
答案 8 :(得分:0)
它被认为是一个读操作。您不会遇到任何竞争条件,但如果您担心获取最新信息,则可以List
volatile
。
答案 9 :(得分:0)
此类型的公共静态(在Visual Basic中为Shared)成员是线程安全的。不保证任何实例成员都是线程安全的。
ReaderWriterLock类似乎是为您正在寻找的同步而构建的。