zoukankan      html  css  js  c++  java
  • 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 = { "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 }
  • 相关阅读:
    魔兽世界服务器Trinitycore分析二:auth server的main函数
    白话经典算法系列之七 堆与堆排序
    Opencv学习笔记(六)SURF学习笔记
    sprintf,你知道多少?
    色相环上面的颜色和相邻颜色的关系是什么
    视达配色教程10 绿色的意向是什么
    网页设计实战3 ufo类型的科技网页如何实现
    如何使用echo.js实现图片的懒加载(整理)
    网页设计实战1 如何实现纸叠登录效果
    人为什么要好好努力学习工作
  • 原文地址:https://www.cnblogs.com/testsec/p/6095984.html
Copyright © 2011-2022 走看看