C# 非线程安全-公共静态列表<;T>;

C# 非线程安全-公共静态列表<;T>;,c#,multithreading,thread-safety,C#,Multithreading,Thread Safety,我在MSDN中读到,当列表用作公共静态类型时,它是线程安全的。然而,下面的代码片段证明了这一点。我试图从列表中添加和删除元素,但是remove方法在中途抛出一个错误,称索引超出范围。这里出了什么问题 这是检验我理论的正确实现吗。如果没有,请有人提出一个更好的例子 class Program { public static List<string> strlist = new List<string>(); public static AutoResetEv

我在MSDN中读到,当列表用作公共静态类型时,它是线程安全的。然而,下面的代码片段证明了这一点。我试图从列表中添加和删除元素,但是remove方法在中途抛出一个错误,称索引超出范围。这里出了什么问题

这是检验我理论的正确实现吗。如果没有,请有人提出一个更好的例子

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();


    }

}
类程序
{
public static List strlist=new List();
public static AutoResetEvent autoEvent=新的AutoResetEvent(false);
静态void Main(字符串[]参数)
{
strlist=新列表();
新线程(()=>
{
对于(int i=0;i{
strlist.ForEach(e=>strlist.Remove(e));
}).Start();
控制台。写入线(“等待”);
autoEvent.WaitOne();
int-ci=0;
ForEach(str=>ci++);
Console.WriteLine(ci.ToString()+“Done”);
Console.Read();
}
}

我在MSDN中读到,当列表用作公共静态类型时,它是线程安全的

那句话不是真的。你可能指的是这段文字:

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


这是指类
列表
的成员。它不是指类
列表

的实例。我认为当他们说“static”时,并不意味着你必须使用static关键字,一切正常。他们的意思是,只要列表是静态的,就像“它永远不会被修改”一样然后您可以从多个线程使用它,而不会出现任何问题。

您的读数不正确。您使用的是实例成员(
.Add()
等);实例成员不是线程安全的;MSDN

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

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


事实上,
List
没有任何静态方法(文本仅声明默认值:静态成员通常是线程安全的;实例成员通常不是线程安全的)

“我在MSDN中读到,列表用作公共静态类型时是线程安全的。”这不是真的。列表的创建是线程安全的,但访问它不是线程安全的(如代码所示)。请链接到此文档。我可以在
list
的文档中看到以下内容:
Public static(在Visual Basic中共享)此类型的成员是线程安全的。
。这与您的断言非常不同。您读错了。请参阅Mark的答案。请再次查看文档。可能是正确的重复。声明为公共静态的“列表”成员是线程安全的。@RitchMelton yes-全部为零。不,静态是指通常预期的API约定:任何静态方法实际上,
List
的所有零静态方法都是线程安全的——为了确保安全,我将所有零读了三遍。