理解GEVENT的协程调度 – 如何在GEVENT里结束一个CPU BOUND 操作
说起这个需求,其实是来自于实现一个Gevent内的代码执行器的逻辑。
这个逻辑要求定时运行某个用户的callback,但是必须不能一直执行这个callback,所以要有Timeout,在Timeout到达的时候,自动kill掉用户的Greenlet.
Gevent自带一个Timeout的实现,同时Greenlet也都表现为DaemonThread运行。
但是经过尝试发现,Gevent的Timeout在这种场景下无法工作。
import gevent
import time
def fucking_loop():
while True:
pass
def fucking_loop_with_timeout():
with gevent.Timeout(10):
while True:
pass
def fail_to_kill():
deadline = time.time() + 10
thread = gevent.spawn(fucking_loop)
while deadline > time.time():
# gevent.sleep will switch out of main thread
gevent.sleep(1)
# This line of code will never been executed
# because gevent will not switch to main thread.
thread.kill()
def fail_to_kill_2():
deadline = time.time() + 10
thread = gevent.spawn(fucking_loop)
# Will never timeout because of the same reason
fucking_loop_with_timeout()
# This line of code will never been executed
# because gevent will not switch to main thread.
thread.kill()
Gevent的Greenlet切换都是发生在等待IO的时候,并不会在需要所有CPU的地方发生切换,因此,对于空的While Loop,Gevent主线程或者说切换器,永远没有机会执行,因为空的while loop会一直吃CPU,而不会触发switch,这样Timeout的执行也就无从谈起了。
关于Gevent切换的讨论,可以参见:
https://groups.google.com/forum/#!topic/gevent/eBj9YQYGBbc
Gevent无法处理这种业务代码的情况下,有没有别的思路或者工具可以处理Timeout这种场景呢?
答案是操作系统的Signal API。
https://docs.python.org/2/library/signal.html
操作系统的SignalAPI会将Callback注册到操作系统的Timer里,这个Timer不受用户态调度器Gevent(Greenlet)的影响,因此不论Gevent的实现逻辑是什么样子的,操作系统都会在时间条件符合设置的时候,调用我们之前注册的Callback,这样一来,我们想要的Timeout功能就可以合理实现了。
最终可以工作的 版本:
import gevent
import time
def fucking_loop():
while True:
pass
def kill_fucking_loop_works():
import signal
timeout = 10
thread = gevent.spawn(fucking_loop)
def kill_thread(*args, **kwargs):
if not thread.dead:
thread.kill(timeout=1)
signal.signal(signal.SIGALRM, kill_thread)
signal.alarm(int(timeout))
文章的确不错啊https://www.cscnn.com/
你的文章让我感受到了正能量,非常棒! https://www.4006400989.com/qyvideo/90868.html
你的文章充满了智慧,让人敬佩。 https://www.4006400989.com/qyvideo/36305.html
《金粉世家》国产剧高清在线免费观看:https://www.jgz518.com/xingkong/35345.html
《红色追击令》国产剧高清在线免费观看:https://www.jgz518.com/xingkong/35346.html
《北京55日》战争片高清在线免费观看:https://www.jgz518.com/xingkong/89886.html
你的才华让人瞩目,期待你的更多文章。 https://www.4006400989.com/qyvideo/83561.html
《我是代办》剧情片高清在线免费观看:https://www.jgz518.com/xingkong/93545.html