信号(semaphore)是一个内核同步对象,用来同步或保护共享资源的访问。通常情况下,对于semaphore设定一个初始值,比如为N。对于每个请求等待semaphore的核心线程(通过调用WaitForThisObject函数),操作如下:
(1)判断N是否小于或等于0,如果不是,则N=N−1,并从等待操作中直接返回。这时候,等待semaphore的线程得以继续执行。
(2)如果N小于或等于0,则说明当前没有可利用资源,于是等待过程把请求的线程插入等待队列,然后执行一个重调度过程。需要注意的是,这种情况下也对N进行递减操作,不过这时候N已经成为负值,因此,如果N大于0,则N的数值代表了当前可用资源的数量,如果N小于0,则N的绝对值代表了当前正在等待semaphore资源的线程的数量(等待队列的长度)。
已经获得信号的线程在执行完关键代码后,必须释放申请的semaphore资源(通过调用ReleaseSemaphore函数)。释放资源的操作(ReleaseSemaphore)过程如下:
(1)对N进行递增(加1)操作,如果N大于0,则说明当前没有线程等待semaphore资源,直接从释放函数中返回。(www.xing528.com)
(2)如果N小于或等于0(递增之后),则说明仍然有线程在等待该信号资源,于是从等待队列中提取一个线程,把该线程修改为就绪(KERNEL_THREAD_STATUS_READY)状态,并插入就绪队列(这样,该线程在合适的时刻会被调度运行),然后返回。
可以看出,一次释放semaphore的操作最多会唤醒一个等待线程,这与事件对象(EVENT)不同,事件对象的一次设置操作可以唤醒所有等待该事件的线程。而如果semaphore的N的值为1,则semaphore演变为一个简单的mutex对象(互斥体对象),可以保护临界区的并发访问。之所以用简单的mutex对象来形容N为1的情况,是因为semaphore对象不支持mutex对象支持的部分功能(比如递归调用等),而仅仅支持mutex对象功能的一个子集。
emaphore的等待操作支持超时等待的方式,即等待的线程可以设定一个时间长度,如果能立即获取资源(等待成功),则直接返回,如果不能立即获取资源被阻塞,则在设定的时间超时后,如果资源仍然不能获得,则也会返回继续执行。这个功能在网络协议的实现中十分有用。
免责声明:以上内容源自网络,版权归原作者所有,如有侵犯您的原创版权请告知,我们将尽快删除相关内容。