白话手动和自动信号量的区别

 

写在前面,这是快餐文章,大侠们尽可一笑而过,对错自辨。

 

  讲到信号,就不得不讲到3种涉众:1. 发信号者;2.传信号者;3.眼巴巴的等着收信号的。
 (看官此时嘘我了,书上可没这么讲过,你瞎叨叨啥呢?)

 

  打个比方,超级大乐透摇奖开始了,全国无数财迷(哦,谢特!打拼音的坏处就是经常出现这种情况,把彩民打成财迷了)就是第3种人,眼巴巴的等着最后的数字,在数字没出炉前,尽管他们中有手心冒汗的,哈喇子吧嗒吧嗒流的,眼睛红了紫、紫了绿的,但他他们都有一个共同点,那就是死,也要死在电视机前,决不挪动半步,“等”就一个字!涉众的第2中就是电视媒体了,它们负责传递实时的信息。第1种显然就是超级大乐透摇奖现场乐。一旦摇出大奖,那些等着的人有的抹了抹口水该干吗干吗去了,有的擦了擦汗睡觉去了,中大奖的准备人间蒸发了,中小奖的准备连夜上大拍档了,在农村没啥消遣的就抱老公搂老婆上炕了,看官,您贵干去了呀?

 

  当然. WINDOWS里信号量是不少的,有用于进程内线程同步的、有由于进程间同步的、有临界资源互斥访问同步的,今天,现在,咱只讨论事件信号。先参考平台SDK里的函数,仅供参考,不看也罢。当然,给看官你带来的损失也罢,哈哈!

 

The CreateEvent function creates or opens a named or unnamed event object.

HANDLE CreateEvent(
 
LPSECURITY_ATTRIBUTES lpEventAttributes,
  BOOL bManualReset,
  BOOL bInitialState,
  LPCTSTR lpName
);


 

The SetEvent function sets the specified event object to the signaled state.

BOOL SetEvent(
 
HANDLE hEvent
);


 

The ResetEvent function sets the specified event object to the nonsignaled state.

BOOL ResetEvent(
 
HANDLE hEvent
);

 

The WaitForSingleObject function returns when the specified object is in the signaled state or the time-out interval elapses.

To enter an alertable wait state, use the WaitForSingleObjectEx function. To wait for multiple objects, use the WaitForMultipleObjects.

DWORD WaitForSingleObject(
 
HANDLE hHandle,
  DWORD dwMilliseconds
);

 

  以上四个函数是最基本的,面向过程的,事件信号控制函数。在.NET里,封装出了ManualResetEvent、AutoResetEvent 两个类,上面四个函数就是这两个类的底层实现。

仔细看虽然有手工和自动信号量两个类,其实对应CreateEvent函数只是第二个参数去TRUE还是FALSE的区别。

 

  那么,手动和自动的是针对什么而言的呢?实际上对信号状态重置是由谁完成来区别的。

手工信号量必须人为编程控制信号到初始状态,自动信号量由操作系统在把信号调度给等待线程中的任何一个线程(调度策略请参考操作系统核心原理方面的书)之后立即自动把信号置为初始状态。

 

  那么,什么叫有信号呢?比如摇奖结果出来后就是有信号了,所以有人沉默、有人悲伤、有欢呼、有尖叫,在此之前,都称为无信号状态,那时大家不都在""吗?

 

  看官您又要问了,信号状态重置又是什么呢?就是把信号量状态恢复到初始状态。

 

  比如: 摇奖结果出来了,你以为地球人都知道了呀?错、错、错!如果你买了彩票突然飞去了墨西哥给人看感冒去了,墨西哥并不转播伟大的中国中央电视台,傻了吧?哪怕是你中了奖,你却高兴不起来,为啥?因为你没收到信号呀(打电话去广电总局问问不就知道了)。这就等同于尽管信号发出了,但其中的等待线程并没有收到信号,这和没发信号就是一样的效果啦。如果知道彩票摇奖结果,从网上找重播录像吧,哈哈!

 

  好了,废话不说了,调试以下两段代码就见分晓了:

 

ManualResetEvent

    

 1  using  System;
 2  using  System.Text;
 3  using  System.Threading;
 4 
 5  namespace  ConsoleApplication1
 6  {
 7       class  Program
 8      {
 9           static  System.Threading.ManualResetEvent e  =   new  System.Threading.ManualResetEvent( false );
10 
11           static   string  resource  =   "" ;
12 
13           static   void  Main( string [] args)
14          {
15              resource  =   " i am wzcheng " ;
16 
17               new  Thread( new  ThreadStart(A)).Start();
18               new  Thread( new  ThreadStart(B)).Start();
19               new  Thread( new  ThreadStart(C)).Start();
20    
21              e.Set();  // 发出信号,此时信号量状态为有信号态,上面三个线程得到运行
22 
23               Thread.CurrentThread.Join( 1000 );
24 
25              Console.WriteLine( " 重置信号量状态按Y,否则按N " );
26 
27               if  ( " N "   ==  Console.ReadLine().ToUpper())
28              {
29                   // 此线程不会被阻塞,因为信号量有信号
30                   new  Thread( new  ThreadStart(D)).Start();
31              }
32               else
33              {
34 
35                  e.Reset();  // 此时信号量状态为无信号态
36 
37                   // 线程阻塞中
38                   new  Thread( new  ThreadStart(D)).Start();
39 
40                  e.Set();  // 发出信号,此时信号量状态为有信号态,上面的线程得到运行
41              }
42 
43              Console.ReadLine();
44          }
45 
46 
47           public   static   void  A()
48          {
49              e.WaitOne();
50              Console.WriteLine( " 对句子进行拼写检查:{0} " ,resource ); 
51          }
52 
53           public   static   void  B()
54          {
55              e.WaitOne();
56              Console.WriteLine( " 对句子进行语法分析:{0} " , resource);
57          }
58 
59           public   static   void  C()
60          {
61              e.WaitOne();
62              Console.WriteLine( " 对句子进行文本处理:{0} " , resource);
63          }
64 
65           public   static   void  D()
66          {
67              e.WaitOne();
68              resource  =   " i am XXX " ;
69              Console.WriteLine( " 清空资源:{0} " , resource);
70          }
71      }
72  }
73 

 

 

AutoResetEvent

 

using  System;
using  System.Text;
using  System.Threading;

namespace  ConsoleApplication1
{
    
class  Program
    {
        
static  System.Threading.AutoResetEvent e  =   new  System.Threading.AutoResetEvent( false );

        
static   string  resource  =   "" ;

        
static   void  Main( string [] args)
        {
            resource 
=   " i am wzcheng " ;

            
new  Thread( new  ThreadStart(A)).Start();
            
new  Thread( new  ThreadStart(B)).Start();
            
new  Thread( new  ThreadStart(C)).Start();
  
            e.Set();
            
/* 发出信号,此时信号量状态为有信号态,上面三个线程中随机一个得到运行。
              因为三个线程等待的是自动信号量,所以在信号量发出信号后,同等机会的三个线程被CPU
              挑选其中一个(这是WINDOWS操作系统调度策略,此时忽略线程优先级)唤醒。
              但随后信号量立即被自动恢复到初始的无信号状态,所以其余两个线程无法运行。
             
*/

            
// 如果希望其它的线程继续得到运行,可以取消线程函数中被注释掉的行  // e.Set();

            Console.ReadLine();
        }


        
public   static   void  A()
        {
            e.WaitOne();
            Console.WriteLine(
" 对句子进行拼写检查:{0} " ,resource );
            
// e.Set();
        }

        
public   static   void  B()
        {
            e.WaitOne();
            Console.WriteLine(
" 对句子进行语法分析:{0} " , resource);
            
// e.Set();
        }

        
public   static   void  C()
        {
            e.WaitOne();
            Console.WriteLine(
" 对句子进行文本处理:{0} " , resource);
            
// e.Set();
        }
 
    }
}

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值