Condition.Signal() 的机制
如果我有如下所示的线程
void thread(){
while() {
lock.acquire();
if(condition not true)
{
Cond.wait()
}
// blah blah
Cond.Signal();
lock.release();
}
}
那么我想我的主要问题是信号线程在 cond.signal() 之后是否继续运行一段时间或立即放弃 CPU?我希望在某些情况下不要在唤醒的线程完成执行之前释放锁,而在其他一些情况下,在发出信号后立即释放锁可能是有益的,而无需等待其他唤醒的线程完成。
据我所知,如果有任何线程在等待条件,那么它们会在 Cond.signal() 上被唤醒。但是 woekn up 是什么意思 - 放入就绪队列还是调度程序确保它立即运行? 信号线程又如何呢?它是否会在发出信号时在相同的条件下进入睡眠状态? ..那么其他线程必须唤醒它才能释放锁?
If I had threads as below
void thread(){
while() {
lock.acquire();
if(condition not true)
{
Cond.wait()
}
// blah blah
Cond.Signal();
lock.release();
}
}
Well I guess my main question is that whether the signalling thread continues running for a while after cond.signal() or immediately gives up the CPU?. I would like it in some cases not to release the lock before the woken up thread finishes execution and in some other cases it may be beneficial to release the lock immediately after signalling, without waiting for the other woken thread to finish.
I understand that if there are any threads waiting on the condition then they get woken up on Cond.signal(). But what do you mean by woekn up - put on the ready queue or does the scheduler make sure that it runs immediately?.
and what about the signalling thread.. does it go to sleep on the same condtion upon signalling? .. so then some other thread has to wake it up to make it release the lock?.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
这在很大程度上取决于您的环境(操作系统、库、语言...)以及同步原语的实现方式。由于你没有具体说明,我只给出一个笼统的答案。
当线程进入睡眠状态时,大多数环境会选择将其从调度程序的就绪队列中删除,并且该线程将放弃其剩余的 CPU 时间。当被唤醒时,线程简单地被放回到就绪队列中,并且下次调度程序从队列中选择它时将恢复执行。
线程也可能会进行一些主动等待(旋转),而不是从调度程序的就绪队列中删除。在这种情况下,线程将立即恢复执行。请注意,由于线程在旋转时仍然可能耗尽 CPU 时间,因此它可能必须等待重新调度才能唤醒。如果您的关键部分非常小并且您不想支付调度开销,那么这是一个有用的策略。
混合方法是在从调度程序的就绪队列中删除线程之前进行少量的主动等待。
至于信号线程,除非您的环境明确指定(我不能有任何原因,但您永远不知道),我不希望对 signal() 的调用以必须唤醒它的方式阻塞。 Signal() 可能必须与调用 signal() 的其他线程同步,但这些是实现细节,您不必对此执行任何操作。
This is in large part dependent on your environment (OS, library, language...) and how the synchronisation primitives are implemented. Since you haven't specified any I'll just give a general answer.
When putting a thread to sleep, most environment will choose to remove it from the scheduler's ready queue and the thread will give up its remaining CPU time. When woken up, the thread is simply placed back into the ready queue and will resume execution the next time the scheduler selects it from the queue.
It's also possible that the thread will do some active waiting (spinning) instead of being removed from the scheduler's ready queue. In this case, the thread will resume execution right away. Note that since a thread can still be run out of CPU of time while spinning, it might have to wait to be rescheduled before waking up. This is a useful strategy if your critical sections are very small and you don't want to pay for the scheduling overheads.
A hybrid approach would be to do a small amount of active waiting before removing the thread from the scheduler's ready queue.
As for the signaling thread, unless specified explicitly by your environment (I can't of any reasons but you never know), I wouldn't expect a call to signal() to block in a way that you have to wake it up. Signal() might have to synchronize itself with other threads calling signal() but those are implementation details and you shouldn't have to do anything about it.