Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/list/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C#List的线程安全性<;T>;给读者_C#_List_Thread Safety_Generic List - Fatal编程技术网

C#List的线程安全性<;T>;给读者

C#List的线程安全性<;T>;给读者,c#,list,thread-safety,generic-list,C#,List,Thread Safety,Generic List,我计划在静态构造函数中创建一次列表,然后让该类的多个实例在不进行任何锁定的情况下并发地读取(并枚举) 本文 MS将螺纹安全问题描述如下: 公共静态(在Visual Basic中共享) 此类型的成员是线程安全的。 任何实例成员都不是 保证线程安全 一个列表可以支持多个读卡器 同时,只要 集合未被修改。 在集合中枚举是不正确的 本质上不是线程安全的 程序在罕见的情况下 枚举与一个或多个 写访问,这是确保 螺纹的安全性在于锁紧螺纹 在整个过程中收集 枚举。允许收集 要由多个线程访问的 阅读和写作,你必

我计划在静态构造函数中创建一次列表,然后让该类的多个实例在不进行任何锁定的情况下并发地读取(并枚举)

本文 MS将螺纹安全问题描述如下:

公共静态(在Visual Basic中共享) 此类型的成员是线程安全的。 任何实例成员都不是 保证线程安全

一个列表可以支持多个读卡器 同时,只要 集合未被修改。 在集合中枚举是不正确的 本质上不是线程安全的 程序在罕见的情况下 枚举与一个或多个 写访问,这是确保 螺纹的安全性在于锁紧螺纹 在整个过程中收集 枚举。允许收集 要由多个线程访问的 阅读和写作,你必须 实现您自己的同步

“枚举集合本质上不是线程安全过程。” 这句话让我担心

这是否意味着它对于只读场景是线程安全的,但前提是不使用枚举

或者对我的场景来说安全吗


谢谢你的回答。 如果AsReadOnly可以使用或不使用,为什么我需要使用它呢

这是否意味着它是线程安全的 仅适用于读者场景,但只要 因为您不使用枚举?或者是 对我的场景来说安全吗

完全取决于您何时写入集合。这不能与没有某种锁定方案的读取(枚举)一致

因此,如果您只填充一次,然后只对其进行迭代,那么您就安全了。但是,当一个线程更改列表(添加或删除项目)时,您将需要例如ReaderWriterLockSlim


更改存储项的状态时,线程安全与该项(而不是列表)有关

这意味着,如果您枚举一个集合,而另一个线程(或您自己的线程)更改了它,那么您将遇到问题


只要您根本不更改集合,只要您不跨线程共享
IEnumerator
,您就不会有任何问题。

是的,列表对于仅读者场景是安全的,如果列表永远不会被修改,那么它就可以了

如果事实上在构建后列表不会被修改,那么您应该使用更合适的界面,如
ReadOnlyCollection
。如果它像您所说的那样存储在公共静态变量中,则应该使用该接口

private static List<T> shared_list;

private static ReadOnlyCollection<T> _data;
public static IEnumerable<T> Data
{
    get
    {
        return _data ?? (_data = shared_list.AsReadOnly());
    }
}
私有静态列表共享\u列表;
私有静态只读收集数据;
公共静态IEnumerable数据
{
得到
{
返回_data???(_data=shared_list.AsReadOnly());
}
}
==编辑====

此版本缓存ReadOnlyCollection引用,以加快将来的查找时间


请注意,如果两个线程在引用为null时同时尝试获取引用,则可能会在_data变量上发生数据争用,但因为所有内容都是只读的,所以这并不重要,我们只会创建一个额外的ReadOnlyCollection对象,这比同步便宜。

请注意,您仍然不能更改原始列表。另外,不要每次获取属性时都调用
AsReadOnly
。根据MSDN文档,AsReadOnly是一个O(1)操作。我相信它只是用一个ReadOnlyCollection来包装,它只是简单地委托给基础集合。所以AsReadOnly应该非常快,但它确实会导致分配,所以我们可以潜在地共享那个内存。我将编辑以反映。在.NET4下,您可以使用泛型惰性类进行初始化。参见
不跨线程共享IEnumerators
您的意思是
不从多个线程访问**同一个枚举器实例**吗?@EugeneBeresovksy:完全正确。