当前位置:  编程技术>.net/c#/asp.net

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

    来源: 互联网  发布时间:2014-10-20

    本文导语:  双向信号和竞赛(Two-Way Signaling and Races) Monitor.Pulse方法的一个重要特性是它是异步执行的,这意味着调用pulse方法并不会阻塞自己等待Monitor.Pulse返回。如果任何一个线程在pulsed 对象上等待,它是不会阻塞的,换句话说,调用Moni...

双向信号和竞赛(Two-Way Signaling and Races)
 
Monitor.Pulse方法的一个重要特性是它是异步执行的,这意味着调用pulse方法并不会阻塞自己等待Monitor.Pulse返回。如果任何一个线程在pulsed 对象上等待,它是不会阻塞的,换句话说,调用Monitor.Pulse对程序不会有什么作用,你可以认为Monitor.Pulse方法被忽略了。
这样Pulse提供了一个单向通信:一个 pulsing线程悄悄的向一个waiting 线程发送信号。
Pulse并不会返回一个值来告诉你waiting线程是否收到信号。

但是有时候我们需要知道waiting线程是否受到信号,例如下面的例子:

代码如下:

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?

实际的输出:

Wassup? (线程等待)
 
在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来通知主线程。
代码如下:

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?");
                }
            }
        }
    }


    
 
 

您可能感兴趣的文章:

  • 如何深入了解线程
  • 深入多线程之:深入分析Interlocked
  • 深入多线程之:解析线程的交会(Thread Rendezvous)详解
  • 深入分析父子线程、进程终止顺序不同产生的结果
  • 深入多线程之:深入生产者、消费者队列分析
  • 深入多线程之:用Wait与Pulse模拟一些同步构造的应用详解
  • 深入Java线程中断的本质与编程原则的概述
  • 深入SQLite多线程的使用总结详解
  • 深入理解线程安全与Singleton
  • 深入多线程之:Wait与Pulse的使用详解
  • 深入探讨linux下进程的最大线程数、进程最大数、进程打开的文件数
  • Java 多线程同步 锁机制与synchronized深入解析
  • 深入Sqlite多线程入库的问题
  • 深入多线程之:Reader与Write Locks(读写锁)的使用详解
  • 深入Android线程的相关问题解惑
  • 深入java线程池的使用详解
  • 深入Android Handler与线程间通信ITC的详解
  • Java线程中断的本质深入理解
  • Android开发笔记之:深入理解多线程AsyncTask
  • 深入多线程之:内存栅栏与volatile关键字的使用分析
  •  
    本站(WWW.)旨在分享和传播互联网科技相关的资讯和技术,将尽最大努力为读者提供更好的信息聚合和浏览方式。
    本站(WWW.)站内文章除注明原创外,均为转载、整理或搜集自网络。欢迎任何形式的转载,转载请注明出处。












  • 相关文章推荐
  • mysql中limit的用法深入分析
  • 深入理解结构体中占位符的用法
  • PHP中redis的用法深入解析
  • C++ using namespace std 用法深入解析
  • C++ Vector用法深入剖析
  • 深入理解atoi()与itoa()函数的用法
  • 深入C++ string.find()函数的用法总结
  • 深入SQL Cursor基本用法的详细介绍
  • 深入理解双指针的两种用法
  • 深入探讨:oracle中row_number() over()分析函数用法
  • 深入DropDownList用法的一些学习总结分析
  • jQuery中.live()方法的用法深入解析
  • pthread_cond_wait() 用法深入分析
  • 深入理解C++中public、protected及private用法
  • 深入C++ typedef的用法总结(必看)
  • Docker支持更深入的容器日志分析
  • 关于《深入浅出MFC》
  • Linux有没有什么好的高级的书,我要深入,
  • 深入理解linux内核
  • [100分]有没有关于binutils的深入的资料?或者深入底层的资料?
  • 深入理解PHP内核 TIPI
  • 想深入学习Java应该学习哪些东西
  • 哪位有《JSP深入编程》电子版?
  • 想要深入学习LINUX该学什么?
  • 100分求:哪儿有《深入理解linux内核》可供下哉!
  • 如何深入Linux的内核学习?
  • U-BOOT得掌握到什么程序,用不用深入去学
  • 想深入了解操作系统该怎么做
  • 深入Sqlite多线程入库的问题 iis7站长之家
  • 问一个《深入理解计算机系统》中的问题
  • ##想买书深入学习linux下的编程,请指教


  • 站内导航:


    特别声明:169IT网站部分信息来自互联网,如果侵犯您的权利,请及时告知,本站将立即删除!

    ©2012-2021,,E-mail:www_#163.com(请将#改为@)

    浙ICP备11055608号-3