不是线程安全的——公共静态列表< >
本文关键字:静态 列表 线程 安全 | 更新日期: 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关键字,一切都可以工作。他们的意思是,只要列表是静态的,就像"它永远不会以任何方式被修改"一样,那么您可以在多个线程中使用它而不会出现任何问题。