随笔分类 - Monitor锁初探
摘要:写下标题,突然发觉有点淫荡了,把旋改成慰,一字之差,效果全然不同,性质也千差万别.淫者见淫,仁者未必仁。本文写作的初衷是探讨lock或者Monitor.Enter的实现是否用到了自旋,也即所谓的spinning。因为网上众多的意见和看法都是lock是C#/NET中关于线程同步的一种轻量级实现,类似于Windows临界区CriticalSection。那麽究竟有多像,像在哪里?由此也激发了一个偷窥者...
阅读全文
摘要:PulseAll MSDN:通知所有的等待线程对象状态的更改。 所以可以理解成所有Wait锁对象的线程都将变成就绪状态。而Pulse顾名思义,只能将排在最前面的Wait就绪。 非常简单吧,下的示例可以说明PulseAll的功能,线程1启动之后会进入Wait状态,紧接着线程3获得锁对象但也马上Wait,然后线程3获得锁对象就PulseAll了。 PulseAll的结果就是前面两个Wait得到释...
阅读全文
摘要:现在我们再回到最初的示例上来,ThreadProc1和ThreadProc2之间通过lock关键字进行同步,加在在这两个线程上的lock就好比两扇大门,而这两扇门同时只允许打开一扇。我们先在第一个线程中打开了第一扇门,那第二个线程就要在第二扇门外徘徊。而要打开第二扇门就应该等待第一扇门的Monitor.Exit,Exit的调用就好比是关上当前的门,通知另外的门可以打开了。但是现在似乎出了点”意外“。但是现在第一扇门打开之后,突然蹦出个Monitor.Wait,这玩意是个人物,它除了让第一个线程处于阻塞状态,还通知第二扇门可以打开了。这也就是说:并不需要等到第一扇门调用Monitor.Exit,
阅读全文
摘要:打开windbg,哦,不对,先把之前的示例程序改一下,如下,我的目的是为了调试获得Monitor.Enter在进入锁对象并等待之的处理逻辑,所以第一个线程率先拥有了锁对象,但是我们看到第一个线程sleep了太长时间(别学我,我只是为了调试Enter方法),从而导致而第二个线程会长时间的进入徘徊等待的状态,重点就是这第二个线程: using System; using System.Colle...
阅读全文
摘要:再来加深一下印象,每一个Object实例都维护一个SyncBlock并通过这个玩意来进行线程的同步,所以Monitor.Wait最终走到这个BOOL SyncBlock::Wait(INT32 timeOut, BOOL exitContext)并不足奇。在SyncBlock内部我们维护了一个所有正在等待此同步索引块的线程的队列,那具体是通过什麽来控制的呢,通过阅读SyncBlock::Wait源...
阅读全文
摘要:// 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. ...
阅读全文
摘要:前面通过Windbg调试步步追踪最后终于发现Wait函数涉及WaitForMultipleObjectsEx的系统调用。 不过这里我还想换一个角度再来追踪一把,这次是通过.Net源码分析进行追踪。 当然,需要首先下载Rotor并配置好,这里假设全部源码文件放在目录d:\sscli20,这里略去不讲。 我们已经知道Wait在托管层最后调用的实际是ObjWait这个函数: [MethodImp...
阅读全文
摘要:Waits until one or all of the specified objects are in the signaled state, an I/O completion routine or asynchronous procedure call (APC) is queued to the thread, or the time-out interval elapses.SyntaxDWORD WINAPI WaitForMultipleObjectsEx( __in DWORD nCount, __in const HANDLE *lpHandles, __in BO...
阅读全文
摘要:调试之前首先将代码编译成可执行文件,并打开运行程序,效果如下,我们看到程序在打印出2之后就Hung住了,而原因我们也很明确,就是Wait惹得。现在通过Windbg attach 这个进程,加载SOS, .load C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\sos.dll使用!threads命令打印出当前托管程序所有的线程,如下:ThreadCount: 4 UnstartedThread: 0 BackgroundThread: 1 PendingThread: 0 DeadThread: 1 Hosted Runtime: no PreEm.
阅读全文
摘要:线程是一个操作系统的概念,线程的同步也涉及到操作系统的知识。但是具体到不同的开发环境和开发语言中,线程的同步各有各的特点。所以我们可能会感兴趣,这些各具特色的线程同步技术是否一定离不开操作系统底层提供的同步技术呢,还是会在实现的过程中加入一些自己的偏方和窍门。O,这个问题太大了,需要慢慢来讨论。先解剖解剖一只小麻雀吧,这里我只对.Net 提供的Monitor类感兴趣,如有分析错误或不到位之处,还希望同学们积极交流反馈。我们知道Managed Code C#中用来线程同步的技术有好几种,而最常用的可能就是加锁了,也即是使用关键词lock。lock的语法如下:lock (_lockObject)
阅读全文

浙公网安备 33010602011771号