最近在做一些代码整理工作,涉及到List 线程安全问题,查了一些资料。网上有些资料说List 增减成员(Add , Remove) 是安全的,但不保证成员属性值访问安全性,及禁止对 List 跨线程遍历访问, 如 foreach 遍历。
可以想象,有些跨线程操作(Add , Remove)List 集合时, 恰好 另一个线程正在通过 foreach遍历, 这时会抛出异常) 。 有改进方案用 for 替代 foreach ,这样仍会报下标越界错误。
因此 , 跨线程遍历list 不安全毋庸置疑。 对List 增减成员是否安全,需要验证才知道。
如下代码:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; namespace testQueue { class Program { static List<int> list = new List<int>(); static ManualResetEvent[] manu; static object LockList = new object(); static void Main(string[] args) { manu = new ManualResetEvent[2]; manu[0] = new ManualResetEvent(false); manu[1] = new ManualResetEvent(false); ThreadPool.QueueUserWorkItem(new WaitCallback(Task1)); ThreadPool.QueueUserWorkItem(new WaitCallback(Task2)); //等待完成 ManualResetEvent.WaitAll(manu); //统计结果: Console.WriteLine("count:{0}", list.Count); Console.ReadKey(); } public static void Task1(object obj) { // lock (LockList) // { for (int i = 0; i < 5000000; i++) { list.Add(i); } // } Console.WriteLine("Task1 complete!"); manu[0].Set(); } public static void Task2(object obj) { // lock (LockList) // { for (int i = 0; i < 5000000; i++) { list.Add(i); } // } Console.WriteLine("Task2 complete!"); manu[1].Set(); } } }
结果:
我们知道, List 集合大小是动态分配的,此处表明,分配List 大小,与对 List 操作 , 应保证在同一线程。 为了避免List 运行中分配大小,在初使化时,设置了List 大小:
static List<int> list = new List<int>(10000000);
再看看结果:
增加线程锁结果:
结论:
此处表明,使用 List 跨线程操作,增减成员也需加锁。否则会有各种问题。
有关线程集合安全访问, 微软在 .Net Framework 4 时,提供了线程安全集合命名空间:
System.Collections.Concurrent
时间: 2024-10-29 11:24:35