zoukankan      html  css  js  c++  java
  • C#多线程技术(二)

    上一篇中讲述了简单的C#多线程程序编写,应该说并不具备太多的难点,这个程序中,我们将编写一个比较特殊的线程,两个线程需要操作同一个List<int>对象:

    代码
     1  class ThreadCollection{
     2         List<int> elements = new List<int>();
     3         public ThreadCollection(){
     4             elements.Add(10);
     5             elements.Add(20);
     6         }
     7     
     8         public void Run()
     9         {
    10             Thread.Sleep(1000);
    11             foreachint item in elements){
    12                 Console.WriteLine("Item (" + item + " ) ");
    13                 Thread.Sleep(1000);
    14             }
    15 
    16         }
    17 
    18         public void Add()
    19         {
    20             Thread.Sleep(1500);
    21             elements.Add(30);
    22         }
    23 
    24     }
    25 
    26 
    27     ThreadCollection coll = new ThreadCollection();
    28     Thread thread3 = new Thread(
    29                new ThreadStart(coll.Run)
    30             );
    31     Thread thread4 = new Thread(
    32                new ThreadStart(coll.Add)
    33     );
    34 
    35     thread3.Start();
    36     thread4.Start();
    37 

     这个时候,系统会抛出一个InvalidOperationException的异常。显然,我们需要修改程序,一种方法是获取elments的一个镜像(snapshot),对镜像(snapshot)进行操作,这个时候,数据内容被获取出来,用到的类为:

    System.Collections.ObjectModel.ReadOnlyCollection。将原先的foreach语句修改为:

    foreach(int item in new ReadOnlyCollection<int>(elements)){...} 

    这种方法是对elements中的元素进行标记,elements中不允许插入数据,因此系统仍旧会爆出错误。彻底的解决方法是使用lock锁块语句,使用lock将需要进行锁的变量传递进来,然后用{}操作需要lock的语句。示例代码如下:

    代码
     1     lock(elements){
     2         foreach (int item in elements)
     3         {
     4             Console.WriteLine("Item (" + item + " ) ");
     5             Thread.Sleep(1000);
     6         }
     7     }
     8 
     9 ///////////////////////////////////////////////////////////
    10 
    11     lock(elements)
    12     {
    13         elements.Add(30);
    14     }

     此外,将elements数据拷贝出来,然后对拷贝出来的数据进行遍历,这个时候,由于写入和读数据是两个完全不同的对象,不存在同步问题,因此,也可以很好运行:

    代码
    1             int[] items;
    2             lock(elements){
    3                  items = elements.ToArray();
    4            }
    5             foreach (int item in items)
    6             {
    7                 Console.WriteLine("Item (" + item + " ) ");
    8                 Thread.Sleep(1000);
    9             }

    显然,这种方法,在数据量较大的情况i下,拷贝的时候需要花费较长的时间,并且需要占据更多的内存。但这种方法容易维护与理解。有时候,这种方法也非常有效,因为拷贝的时候,可能还没有写入较多的数据,数据仍旧在后台进行写入,但前台已经可以对部分这些数据进行操作,而不会明显影响后台操作数据。

  • 相关阅读:
    使用虚拟环境virtualenv/Virtualenvwrapper隔离多个python
    计算机硬件基本知识及Linux的常用命令
    网络电子时钟系统案例
    地铁时钟系统介绍
    北斗校时服务器装置介绍
    网络电子时钟系统成功案例
    高精度统一时钟基准特点
    IEEE1588 PTP对时系统原理及特点
    GPS轨迹发生模拟器介绍
    python urllib模块
  • 原文地址:https://www.cnblogs.com/ubunoon/p/1670819.html
Copyright © 2011-2022 走看看