改善C#程序的157个建议(连载72)

发表于:2011-11-09 09:40

字体: | 上一篇 | 下一篇 | 我要投稿

 作者:陆敏技    来源:51Testing软件测试网采编

  建议72:在线程同步中使用信号量

  所谓线程同步,就是多个线程在某个对象上执行等待(也可理解为锁定该对象),直到该对象被解除锁定。C#中对象的类型分为引用类型和值类型。CLR在这两种类型上的等待是不一样的。我们可以简单地理解为在CLR中,值类型是不能被锁定的,即不能在一个值类型对象上执行等待。而在引用类型上的等待机制,又分为两类:锁定和信号同步。

  锁定使用关键字lock和类型Monitor。两者没有实质区别,前者其实是后者的语法糖。这是最常用的同步技术。

  本建议主要讨论信号同步。信号同步机制中涉及的类型都继承自抽象类WaitHandle,这些类型有EventWaitHandle(类型化为AutoResetEvent、ManualResetEvent)、Semaphore以及Mutex。见类图6-3。

图6-3 同步功能类的类图

  EventWaitHandle(子类为AutoResetEvent、ManualResetEvent)、Semaphore以及Mutex都继承自WaitHandle,所以它们底层的原理是一致的,维护的都是一个系统内核句柄。不过我们仍需简单地区分这三个类的类型。

  EventWaitHandle维护一个由内核产生的布尔类型对象(称为“阻滞状态”),如果其值为false,那么在它上面等待的线程就阻塞。可以调用类型的Set方法将其值设置为true,解除阻塞。EventWaitHandle类型有两个子类AutoResetEvent和ManualResetEvent,它们的区别并不大,本建议接下来会针对它们阐述如何正确使用信号量。

  Semaphore维护一个由内核产生的整型变量,如果其值为0,则在它上面等待的线程就会阻塞;如果其值大于0,则解除阻塞,同时,每解除一个线程阻塞,其值就减1。

  EventWaitHandle和Semaphore提供的都是单应用程序域内的线程同步功能,Mutex则不同,它为我们提供了跨应用程序域阻塞和解除阻塞线程的能力。

  使用信号机制提供线程同步的一个简单例子如下所示:

  1. AutoResetEvent autoResetEvent = new AutoResetEvent(false);  
  2. private void buttonStartAThread_Click(object sender, EventArgs e)  
  3. {  
  4.     Thread tWork = new Thread(() => 
  5.     {  
  6.         label1.Text = "线程启动..." + Environment.NewLine;  
  7.         label1.Text += "开始处理一些实际的工作" + Environment.NewLine;  
  8.         //省略工作代码  
  9.         label1.Text += "我开始等待别的线程给我信号,才愿意继续下去" +   
  10.             Environment.NewLine;   
  11.         autoResetEvent.WaitOne();  
  12.         label1.Text += "我继续做一些工作,然后结束了!";  
  13.         //省略工作代码  
  14.     });  
  15.     tWork.IsBackground = true;  
  16.     tWork.Start();  
  17. }  
  18. private void buttonSet_Click(object sender, EventArgs e)  
  19. {  
  20.     //给在autoResetEvent上等待的线程一个信号  
  21.     autoResetEvent.Set();  
  22. }

  这是一个简单的Winform窗体程序,其中一个按钮负责开启一个新的线程,另一个按钮负责给刚开启的那个线程发送信号。现在详细解释其中发生的事情。

AutoResetEvent autoResetEvent = new AutoResetEvent(false);

  这段代码创建了一个同步类型对象autoResetEvent,它设置自己的默认阻滞状态是false。这意味着任何在它上面进行等待的线程都将被阻滞。所谓等待,就是在线程中应用:

autoResetEvent.WaitOne();

31/3123>
《2023软件测试行业现状调查报告》独家发布~

关注51Testing

联系我们

快捷面板 站点地图 联系我们 广告服务 关于我们 站长统计 发展历程

法律顾问:上海兰迪律师事务所 项棋律师
版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2024
投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

沪ICP备05003035号

沪公网安备 31010102002173号