不是线程安全的——公共静态列表< >

本文关键字:静态 列表 线程 安全 | 更新日期: 2023-09-27 18:15:23

我在MSDN中读到列表作为公共静态类型时是线程安全的。然而,下面的代码片段证明并非如此。我试图从列表中添加和删除元素,但删除方法抛出一个错误中途说索引越界。这里出了什么问题?

这是一个正确的实现来检查我的理论。如果没有,谁能建议一个更好的例子。

class Program
{
    public static List<string> strlist = new List<string>();
    public static AutoResetEvent autoEvent = new AutoResetEvent(false);
    static void Main(string[] args)
    {
        strlist = new List<string>();
        new Thread(() => 
        {
            for(int i=0;i<10000000;i++)
            {
         strlist.Add("item1");
            }
            //Thread.Sleep(5000);
            autoEvent.Set();
        }).Start(); ;
        new Thread(() => {
         strlist.ForEach(e => strlist.Remove(e));
        }).Start();
        Console.WriteLine("Waiting");
        autoEvent.WaitOne();
        int ci = 0;
        strlist.ForEach(str => ci++);
        Console.WriteLine(ci.ToString() + " Done");
        Console.Read();

    }
}

不是线程安全的——公共静态列表< >

我在MSDN中读到,List作为公共静态类型使用时是线程安全的。

那个陈述是不正确的。你可能指的是这段文字:

此类型的公共静态成员是线程安全的。

表示List<T>类的成员不是指的是List<T>类的实例

您的阅读错误。你正在使用实例成员(.Add()等);实例成员不是线程安全的;MSDN对此是明确的。

线程安全

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

只要不修改集合,List<T>可以同时支持多个读取器。在集合中枚举本质上不是线程安全的过程。在枚举与一个或多个写访问竞争的罕见情况下,确保线程安全的唯一方法是在整个枚举期间锁定集合。要允许多个线程访问集合进行读写,必须实现自己的同步。

实际上,List<T> 没有任何静态方法(文本只是断言默认值:静态成员通常是线程安全的;实例成员通常不是线程安全的)

我认为当他们说"static"时,他们并不是说你必须使用static关键字,一切都可以工作。他们的意思是,只要列表是静态的,就像"它永远不会以任何方式被修改"一样,那么您可以在多个线程中使用它而不会出现任何问题。