首页 > 代码库 > C# 在多线程环境中,进行安全遍历操作
C# 在多线程环境中,进行安全遍历操作
本文以List作为操作对象
MSDN官方给出的List的线程安全的说法:
此类型的公共静态成员是线程安全的。但不能保证任何实例成员是线程安全的。
只要不修改该集合,List 就可以同时支持多个阅读器。通过集合枚举在本质上不是一个线程安全的过程。在枚举与一个或多个写访问竞争的罕见情况下,确保线程安全的唯一方法是在整个枚举期间锁定集合。若要允许多个线程访问集合以进行读写操作,则必须实现自己的同步。
如果不进行同步操作?
假如一个线程进行删除操作,一个线程进行遍历操作,那么在遍历过程中,集合被修改,会导致出现InvalidOperationException的异常,提示:集合已修改;可能无法执行枚举操作。
如何同步,保证遍历的安全
这里使用了临界区,互斥锁来保证线程遍历过程的安全,示例代码如下:
1 using System; 2 using System.Collections.Generic; 3 using System.Threading; 4 5 namespace ConsoleApp 6 { 7 class Program 8 { 9 public static List<string> simpleList = new List<string>(); 10 11 public static void Main(string[] args) 12 { 13 // 临界区对象 14 object lockObj = new object(); 15 16 // 向List中添加测试数据 17 string[] data = http://www.mamicode.com/{ "1", "2", "3", "4", "5", "6", "7", "8" }; 18 simpleList.AddRange(data); 19 // 此线程用于遍历数组 20 new Thread(new ThreadStart(() => 21 { 22 // 用于同步,进入临界区,只有遍历完,释放临界区对象的互斥锁,才能进行写操作 23 lock (lockObj) 24 { 25 foreach (var item in simpleList) 26 { 27 Console.WriteLine(item); 28 Thread.Sleep(500); 29 } 30 } 31 })).Start(); 32 // 此线程执行删除操作 33 new Thread(new ThreadStart(() => 34 { 35 lock (lockObj) 36 { 37 simpleList.RemoveAt(0); 38 Console.WriteLine("rm 1"); 39 Thread.Sleep(500); 40 simpleList.RemoveAt(0); 41 Console.WriteLine("rm 2"); 42 } 43 })).Start(); 44 45 Console.ReadLine(); 46 } 47 } 48 }
C# 在多线程环境中,进行安全遍历操作
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。