关于使用EnterCriticalSection思考

郑重声明,分割线以下的内容是错误的,由于我之前对这部分没看完整,故而写出分割线下面的错误内容.在此更正一下.
如果某一时间点有线程在CriticalSection内的话,EnterCriticalSection()会让待进入CriticalSection区域内的其它线程处于等待状态.但是它会将待进入CriticalSection的线程切换到不占用CPU的状态,太棒了!


 

以前一直认为,使用CriticalSection这种方式是实现互斥最节约资源的方式,今天看了<WINDOWS核心编程>的旋转锁,以及提及CriticalSection的实现方式,才发觉我原来的这种想法是错的.

BOOL gfResourceInUse = FALSE;
void Function1()
{
while (InterlockedExchange(&gfResourceInUse, TRUE) == TRUE)
Sleep(0);

// Access the resource.
//...

InterlockedExchange(&gfResourceInUse, FALSE);
}
上面是书中的代码.作者说它是伪代码,CriticalSection的实现方式大概是这样.
基于上面的代码,可以看出,如果多个线程使用这种方式来进入一个CriticalSection的话,当某个线程处于CriticalSection内,那其它的线程将会处于"循环等待"的状态,虽然有Sleep(0),但是这是死循环,在这里等待互斥资源的释放,对CPU的占用率是相当的高. 所以使用CriticalSection只适合在CriticalSection区域内处理的事情是非常简单的,耗时非常短的(程序级别的时间),如果处理事务用的时间比较长的话,就不适合用CriticalSection这种方式来解决问题. 还有一种情况,就是说,CriticalSection区域不会经常的执行,但即使是这种情况,如果CriticalSection区域内的事务执行时间比较长的话,还是不适合使用CriticalSection这种方式来解决问题,因为如果出现某一线程在CriticalSection区域内,而此时正好有其它的线程也要进入CriticalSection区域,那待进入CriticalSection区域的线程将处于等待状态,这个等待状态是很消耗CPU的(CriticalSection的实现方式决定了它消耗CPU).简单来说,就是互斥区域的代码,如果执行的事务比较多,耗时比较长,就不适合使用CriticalSection方式来解决问题(我觉得我有点唐僧了).

书刚看到这个地方,书中应该提及了比较好的解决方案,我还没来的及看.

现在只是说说我的想法吧, 可以使用信号量,或者Event. 让其它要进入互斥区域的线程真正的进入不耗CPU的状态. 当某个线程出了互斥区域后,发出一个信号,或者将事件激活,捕捉到这个事件或者信号的其它线程再进入此互斥区域处理事务.

posted @ 2013-03-18 17:21  莫压枯枯地  阅读(7884)  评论(0编辑  收藏  举报