代码改变世界

一步一步的接近线程同步

2004-09-13 23:55  FantasySoft  阅读(...)  评论(...编辑  收藏
        前几天,我尝试着建立了第一个基于SDK的窗口之后,那个窗口就像是通向一片未知世界的通道一样。我推开窗,发现外面的世界真的很精彩,同时也很无奈,因为我依旧有着很多的迷惑。"问题男"老大指出我的程序应该使用GetMessage方法,这样会在没有消息的时候,线程会被Suspend。如果使用PeekMessage则会几乎耗尽所有的CPU时间。老大的回复促使我重新去看了一下MFC的框架中处理消息循环的代码,同时更促使我去了解GetMessage方法背后的事情。由于没有办法看到这个方法的源代码,只能通过一些资料去总结,去试验,去猜测了。写得不对的地方,还请各位多多指教!
        根据MSDN文档所说的,The GetMessage function retrieves a message from the calling thread's message queue. The function dispatches incoming sent messages until a posted message is available for retrieval。也就是说在线程消息队列里至少有一条消息,方法才会返回。也有文档说,GetMessage方法是一个具有同步行为的方法。而这些从整体来看,关键是同步(synchronization)了。那么就先从同步入手吧。
        查阅了一些资料,对线程同步有了一个较为清晰的认识。线程同步的意义在于保持公共资源在各个线程的一致性。举个例子:对于一个全局变量,一个线程需要修改它,而另外几个线程则需要读取它,那么如果负责修改的线程在修改过程中不禁止其他线程访问这个全局变量的话,则无法保证其他线程读取到的是同一个值。毕竟一个线程修改内存空间的内容是需要时间的。为了实现线程同步,通常利用以下几种机制:Mutex Objects(互斥量)、Semaphore Objects(信号量)、Critical Section Objects(临界区)和Event(事件)。这些内容在很多文档资料中都有讲述,这里就不多说了。那么跟GetMessage方法联系起来,GetMessage操作的结果是从消息队列中取走一条消息,它需要等待队列中存在至少一条消息这样的事件,也就是说当消息队列中存在至少一条消息的时候会变为有信号的状态,GetMessage方法才得以返回。因此我们可以得出GetMessage是通过事件机制来实现同步的。
        在查找线程同步的资料的过程,我还从MSDN中,发现了一个新的面孔——Wait Function。所谓Wait Function就是允许线程阻塞自己的操作的函数。 而Wait Functions只有当一定的条件成立的情况下才会返回,当一个Wait Function被调用的时候,它会去检查返回的条件是否成立,如果不成立则会进入等待状态直到返回的条件成立或者超时,而等待的状态是不会消耗CPU时间的。据此,我们可以推断GetMessage就是属于Wait Function。Wait Function有四类:single-object 、multiple-object 、alertable、registered。从MSDN中的Wait Function Reference中可以找到相应的信息。
        综上所述,GetMessage本身是一个Wait Function,可以实现线程的阻塞,从而进入线程Suspend的状态;同时在Function中通过事件的机制来实现同步。开始一步一步接近线程同步,我想下一步就该是自己写个消息处理函数来替代GetMessage来玩玩了,呵呵~~~