WaitForSingleObject 的讨论

来源:互联网 发布:删除数据库重复数据 编辑:程序博客网 时间:2024/06/06 01:01

问: 
众所周知,在用户模式下等待某一个线程或其他事情的发生是要浪费CPU时间的,但若在内核模式下,比如WaitForSingleObject就不会占用CPU时间(除了两种模式之间的切换时间),那么系统是如何做到的呢,难道她就不需不断检测相应的内核对象吗?若是,那内核对象的结构是什么样的? 
=================================================== 
答: 
首先你要理解多线程也要浪费CPU时间, 
在内核模式下,多个线程并发运行,操作系统按策略给每个线程分配CPU时间片,当一个线程利用WaitForSingleObject进入等待状态时,系统确实需不断检测相应的内核对象,对于线程同步来说,这些内核对象中的每种对象都可以说是处于已通知或未通知的状态之中。这种状态的切换是由Microsoft为每个对象建立的一套规则来决定的。例如,进程内核对象总是在未通知状态中创建的。当进程终止运行时,操作系统自动使该进程的内核对象处于已通知状态。一旦进程内核对象得到通知,它将永远保持这种状态,它的状态永远不会改为未通知状态。进程内核对象中是个布尔值,当对象创建时,该值被初始化为FALSE(未通知状态)。当进程终止运行时,操作系统自动将对应的对象布尔值改为TRUE,表示该对象已经得到通知。 
=================================================== 
问: 
若用WaitForSingleObject进入等待状态时,系统确实需不断检测相应的内核对象,那这与在用户态检测有何不同,我们的程序为何还要花费100个cpu时间进行用户模式和核心模式转换。 
再者“由Microsoft为每个对象建立的一套规则来决定”中的“规则”是如何描述的? 
=================================================== 
答: 
WaitForSingleObject进入等待状态时,进入核心态,由核心中的系统线程帮你检测内核对象,这样是为方便管理。对于一般进程自己独占的对象,我们可以在用户态实现检测,当然你得自己实现它(你自定义这种对象),LINUX中就有相关的应用(用户态的对象),这样比较快,但用户需要考虑的就多。WINDOWS中都为用户管理了,尤其是夸进程的内核对象的应用,用户管理起来比较复杂,所以WINDOWS采用了集中管理。这样虽然会牺牲一定速度,但利于系统的集中管理也省去了用户不少麻烦。当然速度问题,这样说不一定准确,但有时确实会比用户态管理损失速度和自由度。 

下面简单描述一下过程:(不一定很准确) 
线程进入核心态,检查内核对象是否可用,如果不可用,就排队入核心对象的等待线程队列,系统也就不须再为此线程安排运行时间了,当内核对象可用,检测等待队列,去出第一个线程,重新交给调度线程队列安排该线程运行。 

所有的操作系统对此的实现大同小异。 

WaitForSingleObject进入等待状态时,线程进入核心态,由核心的系统线程检测对应的内核对象。对于进程独占的对象,管理比较简单,可以在用户态实现,LINUX中有用户态的对象的应用,这样做自由度大,速度快,但用户需要相应处理。WINDOWS下可自定义实现类似功能。 

WINDOWS为方便管理安全性等特性,集中采用了核心管理,由其对夸进程共享,管理比较复杂,这样减少了不少用户的麻烦。 

简单描述一下过程:(不是很准确) 
线程等待一个核心对象,从用户态进入核心态,检查核心对象是否可用。可用返回,不可用,则排队进入核心对象的等待队列。这样,调度线程就不再为该线程安排CPU。核心对象可用,检查等待队列,如果没有等待线程返回,如果有,则将第一个等待线程取出,放入调度线程队列,调度线程重新为其安排CPU。 
如果在用户态自己实现,少不了循环检查状态,如果多个线程竞争,系统要不断为他们安排CPU让他们运行检查程序,这样必然是耗费CPU。 

原帖 http://lijianmin.blog.chinajavaworld.com/entry/4277/0/