CPU调度单位是线程而不是进程,调度器据以排序的是每个线程的优先级。如果线程A和线程B具有相同优先级,调度器会挑选等待时间比较久的那个。
一、线程调度
调度器会弹性调整线程优先级,以强化系统的反应能力,并且避免任何一个线程一直未能接受CPU的润泽。例如:一般的线程优先级是7,如果它被切换到前台,调度系统可能暂时地把它调升到8或9或更高。对于那些有着输入消息等待被处理的线程,调度系统也会暂时调高其优先级。
二、线程产生
以::CreateThread产生一个线程,并指定一个线程函数,它就是一个worker thread,除非在它的生命中接触到了输入消息,这时候它应该有一个消息循环,以抓取消息,于是该线程就变为UI thread。
CWinThread对象代表一个线程本身。每当你需要一个线程时,不应该在MFC程序中直接调用::CreateThread或_beginthreadex,应该先产生一个CWinThread对象,再调用其成员函数CreateThread或全局函数AfxBeginThread。CWinThread::CreateThread或AfxBeginThread内部调用了beginthreadex。
CWinThread::CreateThread和AfxBeginThread不只是::CreateThread的一层封装,更做了一些application framework所需的内部数据初始化工作,并确保使用正确的C runtime library版本。
1、产生一个Worker Thread
CWinThread *pThread = AfxBeginThread(ThreadFunc, ¶m); UINT ThreadFunc(LPVOID param) { }
2、产生一个UI Thread
UI Thread不能够由一个函数来代表,应该先从CWinThread派生出一个自己的类,再调用AfxBeginThread产生一个CWinThread对象。
注意:
(1)线程函数是由系统调用的,也就是一个callback函数,不容许有this指针参数。所以任何一般的C++类成员函数都不能拿来当线程函数,它必须是个全局函数或是个C++类的static成员函数。
(2)比较好的做法是把所有UI操作都集中在主线程,其他的“纯运算操作”才考虑交给Worker Thread去做。
三、线程结束
Worker Thread的生命就是线程函数本身,函数一旦return,线程结束。或者线程函数调用AfxEndThread结束一个线程。UI Thread因为有消息循环的关系,必须在消息队列中放一个WM_QUIT,才能结束线程。或在线程的任何一个函数中调用AfxEndThread也可以结束线程。
AfxEndThread内部调用_endthreadex,由它结束线程。
四、线程与同步控制
Windows系统提供了四种同步化机制,MFC也提供了四个对应的类。
(1)Critical Section(关键区域)。
(2)Semaphore(信号量)。
(3)Event(事件)。
(4)Mutex(互斥器)。