我从来没有想过这一点,所以我写这个剧本:
import time
while True:
print "loop"
time.sleep(0.5)
正如一个考验。与strace -o isacontextswitch.strace -s512 python test.py运行这个给你环路输出:
write(1, "loop\n", 5) = 5
select(0, NULL, NULL, NULL, {0, 500000}) = 0 (Timeout)
write(1, "loop\n", 5) = 5
select(0, NULL, NULL, NULL, {0, 500000}) = 0 (Timeout)
write(1, "loop\n", 5) = 5
select(0, NULL, NULL, NULL, {0, 500000}) = 0 (Timeout)
write(1, "loop\n", 5) = 5
select(0, NULL, NULL, NULL, {0, 500000}) = 0 (Timeout)
write(1, "loop\n", 5)
select()是一个系统调用,所以是的,你是上下文切换(OK技术上当你切换到内核空间上下文切换实际上不是必要的,但如果您还有其他进程在运行,那么您在这里所说的是,除非您有数据准备好读取文件描述符,否则其他进程可以运行到内核中以执行此操作。有趣的是,延迟是在stdin上进行选择。这允许python中断你对输入的输入,如果他们希望,而不必等待代码超时 - 我认为它很整洁。
我应该注意,除了传入的时间参数是{0,0}之外,同样适用于time.sleep(0)。而且这种旋转锁定对于任何情况都不是很理想,但很短的延迟 - multiprocessing和threads提供了等待事件对象的能力。
编辑:所以我有一个看看究竟是什么Linux的。在do_select(fs\select.c)的实施,使得这一检查:
if (end_time && !end_time->tv_sec && !end_time->tv_nsec) {
wait = NULL;
timed_out = 1;
}
if (end_time && !timed_out)
slack = select_estimate_accuracy(end_time);
换句话说,如果提供的结束时间和两个参数是零(0 = 1,并评估在C真!)然后等待被设置为NULL并且选择被认为超时。但是,这并不意味着该函数会返回给您;它循环遍历所有文件描述符并调用cond_resched,从而可能允许另一个进程运行。换句话说,发生什么事完全取决于调度程序。如果您的进程占用CPU时间与其他进程相比较,则可能会发生上下文切换。如果没有,你所在的任务(内核do_select函数)可能会继续执行,直到完成。
但是,我会重复说明,对其他进程更好的最佳方式通常涉及使用除自旋锁之外的其他机制。