AutoResetEvent的进一步分析

前几天根据MSDN中提供的关于AutoResetEvent的一段示例代码分析了AutoResetEvent的使用,为了加深理解,我对代码做了进一步扩展,是这样的,原始的程序包括2个线程:主线程用来写,附加的线程用于读取,读取需要在写完成之后进行,采用了信号通知的机制,能够确保一写一读的顺序,也就是说不会发生混乱,其中关键点就是一个AutoResetEvent这个类。

我的扩展是这样的,我先写,然后改变该值(我在这里就是把number加1),然后再将它读取出来。

试验的过程如下,首先创建一个新的函数准备用于第三个线程当中,这个方法名称是:ChangeValueThread,代码如下:

static void ChangeValueThread()
  {
   while(true)
   {
    //ChangeEvent.WaitOne();
    number+=1;
    Console.WriteLine("{0} change value: {1}", Thread.CurrentThread.Name, number); 
    //myResetEvent.Set();
    Thread.Sleep(1000);
   }
  }

首先使用一个信号,也就是原始代码中的myResetEvent,把它同时用在这个方法中,也就是说,有2个线程都在等待这一个事件信号,代码如下:

using System;
using System.Threading;

namespace AutoResetEvent_Examples
{
 class MyMainClass
 {
  //初始化,未信号
  const int numIterations = 50;
  static AutoResetEvent myResetEvent = new AutoResetEvent(false);
  static AutoResetEvent ChangeEvent=new AutoResetEvent(false);
  static int number; //这是关键资源
    
  static void Main()
        {
        //创建并开始读者线程
        Thread myReaderThread = new Thread(new ThreadStart(MyReadThreadProc));
        myReaderThread.Name = "ReaderThread";
  Thread ChangeThread=new Thread(new ThreadStart(ChangeValueThread));
  ChangeThread.Name="ChangeThread";
  ChangeThread.Start();
        myReaderThread.Start();
  //----------------------------------------------------------------
  //说明:
  //启动之后会有什么变化,会读取吗?从程序的执行结果看,读者线程一启动
  //并没有执行代码,也就是说,一启动首先就处于等待状态了
  //----------------------------------------------------------------
         for(int i = 1; i <= numIterations; i++)
         {
            Console.WriteLine("Writer thread writing value: {0}", i);
            number = i;
           
            //Signal that a value has been written.
            myResetEvent.Set();
            //给读者线程一个动作的机会,这里我试验了好几个参数:0,1,10
     //结果是,采用0整个应用的运行速度明显的最快,采用1和10,速度
     //有明显下降,但是使用0的时候,CPU很忙。
            Thread.Sleep(0);
         }

         //终止读者线程
         myReaderThread.Abort();
  ChangeThread.Abort();
      }

      static void MyReadThreadProc()
      {
         while(true)
         {
            //在值被写入之前不会被读取,在上次读取之后至少有一次
            myResetEvent.WaitOne();
            Console.WriteLine("{0} reading value: {1}", Thread.CurrentThread.Name, number);
         }
      }
  static void ChangeValueThread()
  {
   while(true)
   {
    myResetEvent.WaitOne();    
    number+=1;
    Console.WriteLine("{0} change value: {1}", Thread.CurrentThread.Name, number); 
    Thread.Sleep(0);
   }
  }
    }
}

得到的输出如下所示:

D:/学习/VS2003Project/线程>th
Writer thread writing value: 1
ChangeThread change value: 2
Writer thread writing value: 2
ReaderThread reading value: 2
Writer thread writing value: 3
ReaderThread reading value: 3
Writer thread writing value: 4
ReaderThread reading value: 4
Writer thread writing value: 5
ReaderThread reading value: 5
Writer thread writing value: 6
ReaderThread reading value: 6
Writer thread writing value: 7
ReaderThread reading value: 7
Writer thread writing value: 8
ReaderThread reading value: 8
Writer thread writing value: 9
ReaderThread reading value: 9
Writer thread writing value: 10
ChangeThread change value: 11
Writer thread writing value: 11
ReaderThread reading value: 11
Writer thread writing value: 12
ReaderThread reading value: 12
Writer thread writing value: 13
ReaderThread reading value: 13
Writer thread writing value: 14
ReaderThread reading value: 14
Writer thread writing value: 15
ReaderThread reading value: 15
Writer thread writing value: 16
ReaderThread reading value: 16
Writer thread writing value: 17
ReaderThread reading value: 17
Writer thread writing value: 18
ReaderThread reading value: 18
Writer thread writing value: 19
ReaderThread reading value: 19
Writer thread writing value: 20
ChangeThread change value: 21
Writer thread writing value: 21
ReaderThread reading value: 21
Writer thread writing value: 22
ReaderThread reading value: 22
Writer thread writing value: 23
ReaderThread reading value: 23
Writer thread writing value: 24
ReaderThread reading value: 24
Writer thread writing value: 25
ReaderThread reading value: 25
Writer thread writing value: 26
ReaderThread reading value: 26
Writer thread writing value: 27
ReaderThread reading value: 27
Writer thread writing value: 28
ReaderThread reading value: 28
Writer thread writing value: 29
ReaderThread reading value: 29
Writer thread writing value: 30
ChangeThread change value: 31
Writer thread writing value: 31
ReaderThread reading value: 31
Writer thread writing value: 32
ReaderThread reading value: 32
Writer thread writing value: 33
ReaderThread reading value: 33
Writer thread writing value: 34
ReaderThread reading value: 34
Writer thread writing value: 35
ReaderThread reading value: 35
Writer thread writing value: 36
ReaderThread reading value: 36
Writer thread writing value: 37
ReaderThread reading value: 37
Writer thread writing value: 38
ReaderThread reading value: 38
Writer thread writing value: 39
ReaderThread reading value: 39
Writer thread writing value: 40
ChangeThread change value: 41
Writer thread writing value: 41
ReaderThread reading value: 41
Writer thread writing value: 42
ReaderThread reading value: 42
Writer thread writing value: 43
ReaderThread reading value: 43
Writer thread writing value: 44
ReaderThread reading value: 44
Writer thread writing value: 45
ReaderThread reading value: 45
Writer thread writing value: 46
ReaderThread reading value: 46
Writer thread writing value: 47
ReaderThread reading value: 47
Writer thread writing value: 48
ReaderThread reading value: 48
Writer thread writing value: 49
ReaderThread reading value: 49
Writer thread writing value: 50
ChangeThread change value: 51

D:/学习/VS2003Project/线程>

我们看到出现了线程的执行的不稳定,有些结果丢失了。分析原因,同一个信号对象,通过Set来置位,置位之后就释放了等待的线程,我们从执行结果看到,的确有2个线程在执行,其中一个是主线程,也就是写线程,另外一个是不确定的,也许是Reader线程,也许是Change线程。说明出现了线程的争用,从执行的结果来看,总是2个线程在运行,根据分析也应该是有且只有2个线程会运行,因为,这由myResetEvent来确定,它[外部主线程]发信号,释放等待线程,回到非终止状态,其中一个线程被释放,该信号就会回到非终止状态了,另外一个线程应该是没有机会的。只是这种分析还需要求证。

现在,我需要协调3个线程的运行,一个主线程,2个工作线程,主线程还是写,2个工作线程分别是改变和读取。我认为,这一定需要2个信号才能完成,实际上这样做可以,我只是不知道是否还有更好的办法。

代码如下:

using System;
using System.Threading;

namespace AutoResetEvent_Examples
{
 class MyMainClass
 {
  //初始化,未信号
  const int numIterations = 50;
  static AutoResetEvent myResetEvent = new AutoResetEvent(false);
  static AutoResetEvent ChangeEvent=new AutoResetEvent(false);
  static int number; //这是关键资源
    
  static void Main()
        {
        //创建并开始读者线程
        Thread myReaderThread = new Thread(new ThreadStart(MyReadThreadProc));
        myReaderThread.Name = "ReaderThread";
  Thread ChangeThread=new Thread(new ThreadStart(ChangeValueThread));
  ChangeThread.Name="ChangeThread";
  ChangeThread.Start();
        myReaderThread.Start();
  //----------------------------------------------------------------
  //说明:
  //启动之后会有什么变化,会读取吗?从程序的执行结果看,读者线程一启动
  //并没有执行代码,也就是说,一启动首先就处于等待状态了
  //----------------------------------------------------------------
         for(int i = 1; i <= numIterations; i++)
         {
            Console.WriteLine("Writer thread writing value: {0}", i);
            number = i;
           
            //发信号,说明写已经完成
//            myResetEvent.Set();
   //向更改线程发信号,说明写已经完成
            ChangeEvent.Set();
            //给读者线程一个动作的机会,这里我试验了好几个参数:0,1,10
   //结果是,采用0整个应用的运行速度明显的最快,采用1和10,速度
   //有明显下降,但是使用0的时候,CPU很忙。
            Thread.Sleep(0);
         }

         //终止读者线程
         myReaderThread.Abort();
   ChangeThread.Abort();
      }

      static void MyReadThreadProc()
      {
         while(true)
         {           
            myResetEvent.WaitOne();   //等待上一个操作的完成信号
            Console.WriteLine("{0} reading value: {1}", Thread.CurrentThread.Name, number);
         }
      }
  static void ChangeValueThread()
  {
   while(true)
   {
    ChangeEvent.WaitOne(); //等待写完成
    number+=1;
    Console.WriteLine("{0} change value: {1}", Thread.CurrentThread.Name, number); 
    myResetEvent.Set();  //发信号,通知更改完成
    Thread.Sleep(0);
   }
  }
    }
}

我们看看这段程序的执行结果:

D:/学习/VS2003Project/线程>th
Writer thread writing value: 1
ChangeThread change value: 2
ReaderThread reading value: 2
Writer thread writing value: 2
ChangeThread change value: 3
ReaderThread reading value: 3
Writer thread writing value: 3
ChangeThread change value: 4
ReaderThread reading value: 4
Writer thread writing value: 4
ChangeThread change value: 5
ReaderThread reading value: 5
Writer thread writing value: 5
ChangeThread change value: 6
ReaderThread reading value: 6
Writer thread writing value: 6
ChangeThread change value: 7
ReaderThread reading value: 7
Writer thread writing value: 7
ChangeThread change value: 8
ReaderThread reading value: 8
Writer thread writing value: 8
ChangeThread change value: 9
ReaderThread reading value: 9
Writer thread writing value: 9
ChangeThread change value: 10
ReaderThread reading value: 10
Writer thread writing value: 10
ChangeThread change value: 11
ReaderThread reading value: 11
Writer thread writing value: 11
ChangeThread change value: 12
ReaderThread reading value: 12
Writer thread writing value: 12
ChangeThread change value: 13
ReaderThread reading value: 13
Writer thread writing value: 13
ChangeThread change value: 14
ReaderThread reading value: 14
Writer thread writing value: 14
ChangeThread change value: 15
ReaderThread reading value: 15
Writer thread writing value: 15
ChangeThread change value: 16
ReaderThread reading value: 16
Writer thread writing value: 16
ChangeThread change value: 17
ReaderThread reading value: 17
Writer thread writing value: 17
ChangeThread change value: 18
ReaderThread reading value: 18
Writer thread writing value: 18
ChangeThread change value: 19
ReaderThread reading value: 19
Writer thread writing value: 19
ChangeThread change value: 20
ReaderThread reading value: 20
Writer thread writing value: 20
ChangeThread change value: 21
ReaderThread reading value: 21
Writer thread writing value: 21
ChangeThread change value: 22
ReaderThread reading value: 22
Writer thread writing value: 22
ChangeThread change value: 23
ReaderThread reading value: 23
Writer thread writing value: 23
ChangeThread change value: 24
ReaderThread reading value: 24
Writer thread writing value: 24
ChangeThread change value: 25
ReaderThread reading value: 25
Writer thread writing value: 25
ChangeThread change value: 26
ReaderThread reading value: 26
Writer thread writing value: 26
ChangeThread change value: 27
ReaderThread reading value: 27
Writer thread writing value: 27
ChangeThread change value: 28
ReaderThread reading value: 28
Writer thread writing value: 28
ChangeThread change value: 29
ReaderThread reading value: 29
Writer thread writing value: 29
ChangeThread change value: 30
ReaderThread reading value: 30
Writer thread writing value: 30
ChangeThread change value: 31
ReaderThread reading value: 31
Writer thread writing value: 31
ChangeThread change value: 32
ReaderThread reading value: 32
Writer thread writing value: 32
ChangeThread change value: 33
ReaderThread reading value: 33
Writer thread writing value: 33
ChangeThread change value: 34
ReaderThread reading value: 34
Writer thread writing value: 34
ChangeThread change value: 35
ReaderThread reading value: 35
Writer thread writing value: 35
ChangeThread change value: 36
ReaderThread reading value: 36
Writer thread writing value: 36
ChangeThread change value: 37
ReaderThread reading value: 37
Writer thread writing value: 37
ChangeThread change value: 38
ReaderThread reading value: 38
Writer thread writing value: 38
ChangeThread change value: 39
ReaderThread reading value: 39
Writer thread writing value: 39
ChangeThread change value: 40
ReaderThread reading value: 40
Writer thread writing value: 40
ChangeThread change value: 41
ReaderThread reading value: 41
Writer thread writing value: 41
ChangeThread change value: 42
ReaderThread reading value: 42
Writer thread writing value: 42
ChangeThread change value: 43
ReaderThread reading value: 43
Writer thread writing value: 43
ChangeThread change value: 44
ReaderThread reading value: 44
Writer thread writing value: 44
ChangeThread change value: 45
ReaderThread reading value: 45
Writer thread writing value: 45
ChangeThread change value: 46
ReaderThread reading value: 46
Writer thread writing value: 46
ChangeThread change value: 47
ReaderThread reading value: 47
Writer thread writing value: 47
ChangeThread change value: 48
ReaderThread reading value: 48
Writer thread writing value: 48
ChangeThread change value: 49
ReaderThread reading value: 49
Writer thread writing value: 49
ChangeThread change value: 50
ReaderThread reading value: 50
Writer thread writing value: 50
ChangeThread change value: 51
ReaderThread reading value: 51

D:/学习/VS2003Project/线程>

从执行结果来看,它是我们需要的,按照我们设想的顺序执行了,也就是先写,再改,最后读取,没有丢失任何结果。

对于恢复非终止状态的时机,以及等待的线程的代码范围还不是很清楚。这里说的代码范围就是说AutoResetEvent的WaitOne()控制的代码范围,是否是包含这句话的整个线程全部挂起等待?

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值