打印方法和GIL

时间:2018-09-14 04:50:58

标签: python multithreading gil

我有一个多线程程序,最近遇到了一个有趣的现象。

如果我在线程的工作程序中调用print方法,程序将变得非常被动。没有什么大把戏,只需调用print方法即可解决所有问题。

我最近读了一篇有关Python的Global Interpreter Lock aka GIL的文章,它说一旦执行I / O绑定的东西,GIL就被释放。您是否认为print调用也是I / O绑定的?

我真的很想让我的程序具有响应性,但是在运行时将数据转储到stdout上显然很尴尬。因此,我尝试将输出重定向到/dev/null,但未能解决问题:

with contextlib.redirect_stdout(None):
    print('')

如果您有一个主意,希望能通过以下调用重现相同的效果,但又不丢失任何内容,请多加感谢:

print('')

据我所见,解释器为print('')工作时释放了GIL。也许我需要短暂休息一下,让我摆脱GIL。

这仅供参考,但我尝试调用以下方法:

print('', end='', flush=True)

当然,它没有转储任何东西,但我的程序变得有点锯齿,看起来该线程已经占用了执行时间,因此其他线程很少运行。

更新

如果我呼叫QThread的usleep(1)希望让它睡1个小时,那么它的等待时间将比我指定的要长得多。例如。线程工作程序每1毫秒运行一次,这非常慢,因为我希望以微秒的顺序运行它。调用print('')使线程以几微秒的顺序运行。在这种意义上,我称之为反应性。

更新

我觉得有些事情在浪费线程的执行时间,但不是usleeptime.sleep()。但是,我遇到了一个事实,print可以将阻止程序踢开。所以我想知道实际上是什么在踢阻拦物。

1 个答案:

答案 0 :(得分:1)

因此,这里发生了两件事。首先,对于GIL本身,大多数I / O函数都会在调用平台代码之前将其释放,因此,print调用肯定会释放它。这自然会让运行时调度另一个线程。

第二,对于usleep,此功能可以保证至少休眠 与您要求的一样多,而几乎不休眠 OS调度程序刻度的持续时间。在Linux上,它通常以1,000 Hz,250 Hz或100 Hz的频率运行,但可能会有很大差异。

现在,如果您想要更细粒度的内容,可以进行nanosleep调用,该调用将“忙等待”不到2 ms的延迟,而不是调用内核。