现在我们再回到最初的示例上来,ThreadProc1和ThreadProc2之间通过lock关键字进行同步,加在在这两个线程上的lock就好比两扇大门,而这两扇门同时只允许打开一扇。我们先在第一个线程中打开了第一扇门,那第二个线程就要在第二扇门外徘徊。而要打开第二扇门就应该等待第一扇门的Monitor.Exit,Exit的调用就好比是关上当前的门,通知另外的门可以打开了。但是现在似乎出了点”意外“。但是现在第一扇门打开之后,突然蹦出个Monitor.Wait,这玩意是个人物,它除了让第一个线程处于阻塞状态,还通知第二扇门可以打开了。这也就是说:并不需要等到第一扇门调用Monitor.Exit, Read More
打开windbg,哦,不对,先把之前的示例程序改一下,如下,我的目的是为了调试获得Monitor.Enter在进入锁对象并等待之的处理逻辑,所以第一个线程率先拥有了锁对象,但是我们看到第一个线程sleep了太长时间(别学我,我只是为了调试Enter方法),从而导致而第二个线程会长时间的进入徘徊等待的状态,重点就是这第二个线程: using System; using System.Colle... Read More
再来加深一下印象,每一个Object实例都维护一个SyncBlock并通过这个玩意来进行线程的同步,所以Monitor.Wait最终走到这个BOOL SyncBlock::Wait(INT32 timeOut, BOOL exitContext)并不足奇。在SyncBlock内部我们维护了一个所有正在等待此同步索引块的线程的队列,那具体是通过什麽来控制的呢,通过阅读SyncBlock::Wait源... Read More
// We maintain two queues for SyncBlock::Wait. // 1. Inside SyncBlock we queue all threads that are waiting on the SyncBlock. // When we pulse, we pick the thread from this queue using FIFO. ... Read More
前面通过Windbg调试步步追踪最后终于发现Wait函数涉及WaitForMultipleObjectsEx的系统调用。 不过这里我还想换一个角度再来追踪一把,这次是通过.Net源码分析进行追踪。 当然,需要首先下载Rotor并配置好,这里假设全部源码文件放在目录d:\sscli20,这里略去不讲。 我们已经知道Wait在托管层最后调用的实际是ObjWait这个函数: [MethodImp... Read More