我有一个主线程执行一些CPU密集型操作。线程必须为其所有计算保持锁定。
然后还有一些其他线程偶尔会在短暂的时间内需要相同的锁定。
如果没有其他线程,我如何强制主线程偶尔允许其他线程执行而不减慢速度?
定期
lock.release()
time.sleep(x)
lock.acquire()
对于某些x会将控制传递给另一个线程,但如果没有其他线程,则将主线程减慢。
另一方面,如果没有sleep()
调用,GIL似乎会干扰此处。由于主线程在执行release()
时具有GIL,因此另一个线程显然无法立即从acquire()
返回。因此,主线程继续使用自己的acquire()
方法,其他线程永远不会获得锁定,除非GIL切换恰好与我释放自己的锁定完全一致。
这个问题的正确解决方案是什么?有没有办法强制GIL发布?基本上我想要一些神奇的代码,以确保在下面的测试脚本中第二个线程总是首先得到锁:
import threading
import time
class t1 (threading.Thread):
def run(self):
print "Second thread waiting for lock"
lock.acquire()
print "Second thread got lock"
lock.release()
lock = threading.Lock()
lock.acquire()
t = t1()
t.start()
time.sleep(1)
lock.release()
time.sleep(0) # this works very often, but not all the time
lock.acquire()
print "Main thread got lock"
lock.release()
答案 0 :(得分:3)
仅发布GIL并不能保证其他线程有机会运行。
在Unix中,您真正想要的电话是sched_yield()
。 Python标准库中没有该函数的接口;用原生模块添加一个是直截了当的。
usleep(0)
和select()
有时用于相同的目的,但根据系统调度程序的不同,它并不总是相同的。 Windows,你想睡眠(0)。对这两个使用time.sleep(0)。
答案 1 :(得分:0)
以超时0调用select.select()
将暂时释放GIL。