【问题标题】:Not thread safe - public static List<T>不是线程安全的 - public static List<T>
【发布时间】:2011-11-20 04:53:48
【问题描述】:

我在 MSDN 中读到 List 在用作公共静态类型时是线程安全的。但是,以下代码 sn-p 证明并非如此。我正在尝试从列表中添加和删除元素,但是 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();


    }

}

【问题讨论】:

  • “我在 MSDN 中读到 List 在用作公共静态类型时是线程安全的。”这不是真的。列表的 创建 是线程安全的,但访问它不是(如您的代码所示)。
  • 请链接到此文档。我可以在List&lt;T&gt; 的文档中看到以下内容:Public static (Shared in Visual Basic) members of this type are thread safe.。这与您的断言非常不同。
  • 你读错了。见马克的回答。再次查看文档。

标签: c# multithreading thread-safety


【解决方案1】:

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

这种说法是不正确的。您可能指的是这段文字:

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

指的是List&lt;T&gt; 类的成员。它确实引用List&lt;T&gt;类的实例

【讨论】:

    【解决方案2】:

    您的阅读不正确。您正在使用实例成员(.Add() 等);实例成员不是线程安全的; MSDNis explicit about this.

    线程安全

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

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

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

    【讨论】:

    • 对。声明为 public static 的 'List' 成员是线程安全的。
    • @RitchMelton 是的 - 都是零。
    【解决方案3】:

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

    【讨论】:

    • 不,静态的意思是通常的预期 API 约定:任何静态方法都是线程安全的。事实上,List&lt;T&gt; 的所有零静态方法都是线程安全的——为了确定,我读了三遍所有的零。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-26
    • 2011-08-17
    • 2014-08-04
    • 2010-11-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多