源码网商城,靠谱的源码在线交易网站 我的订单 购物车 帮助

源码网商城

深入多线程之:双向信号与竞赛的用法分析

  • 时间:2022-09-27 02:47 编辑: 来源: 阅读:
  • 扫一扫,手机访问
摘要:深入多线程之:双向信号与竞赛的用法分析
[b]双向信号和竞赛(Two-Way Signaling and Races) [/b]  Monitor.Pulse方法的一个重要特性是它是异步执行的,这意味着调用pulse方法并不会阻塞自己等待Monitor.Pulse返回。如果任何一个线程在pulsed 对象上等待,它是不会阻塞的,换句话说,调用Monitor.Pulse对程序不会有什么作用,你可以认为Monitor.Pulse方法被忽略了。 这样Pulse提供了一个单向通信:一个 pulsing线程悄悄的向一个waiting 线程发送信号。 Pulse并不会返回一个值来告诉你waiting线程是否收到信号。 但是有时候我们需要知道waiting线程是否受到信号,[b]例如下面的例子: [/b]
[u]复制代码[/u] 代码如下:
class Race     {         static readonly object _locker = new object();         static bool  _go;         public static void MainThread()         {             new Thread(SaySomething).Start();             for (int i = 0; i < 5; i++)             {                 lock (_locker)                 {                     _go = true;                     Monitor.PulseAll(_locker); //通知等待的队列                 }             }         }         static void SaySomething()         {             for (int i = 0; i < 5; i++)             {                 lock (_locker)                 {                     while (!_go) Monitor.Wait(_locker); //如果_go 为false,那么开始阻塞。                     _go = false;                     Console.WriteLine("Wassup?");                 }             }         }     }
期待的输出: Wassup? Wassup? Wassup? Wassup? Wassup? 实际的输出: [b]Wassup? (线程等待) [/b]  在SaySomething方法中,for循环执行到while,此时_go为false,所以Monitor.Wait开始等待。在MainThread中,for循环设置_go为true。然后PulseAll.但是PulseAll方法是异步的。 所以在SaySomething线程被唤醒前,mainThread中的for循环可能已经执行完毕。所以SaySomething方法中的第一个Wait线程收到消息词是_go为true,所以往下执行,再次将_go字段设置为false。输出”Wassup?”,但是下次循环由于_go为false,所以需要再次wait.所以实际的输出打印了一个Wassup,然后开始等待。 我们需要主线程在每一次迭代中如果worker仍然在执行上一个任务,那么主线程阻塞。等到worker执行完毕,那么主线程恢复执行,然后执行迭代。 我们可以增加一个_ready 标志,从而控制主线程在设置_go 标志之前worker线程已经ready了。也就是说主线程在设置_go之前,会等待worker完成任务,然后等待worker将ready设为true,当worker将ready设置为true后,通过pulse来通知主线程。
[u]复制代码[/u] 代码如下:
class Race     {         static readonly object _locker = new object();         static bool _ready, _go;         public static void MainThread()         {             new Thread(SaySomething).Start();             for (int i = 0; i < 5; i++)             {                 lock (_locker)                 {                     while (!_ready) Monitor.Wait(_locker); //如果worker的ready为false,则等待worker。                     _ready = false; //重置标志                     _go = true;                     Monitor.PulseAll(_locker);                 }             }         }         static void SaySomething()         {             for (int i = 0; i < 5; i++)             {                 lock (_locker)                 {                     _ready = true; //将ready设置为true                     Monitor.PulseAll(_locker); //通知主线程,worker已经ready了,可以执行任务了。                     while (!_go) Monitor.Wait(_locker);                     _go = false;                     Console.WriteLine("Wassup?");                 }             }         }     }
  • 全部评论(0)
联系客服
客服电话:
400-000-3129
微信版

扫一扫进微信版
返回顶部