线程在Python中如何工作,以及特定于Python线程的常见陷阱是什么?

时间:2020-03-05 18:44:09  来源:igfitidea点击:

我一直在努力地思考线程在Python中的工作方式,而且很难找到有关它们如何运行的良好信息。我可能只是缺少链接之类的东西,但是官方文档似乎对该主题并不十分详尽,而且我也找不到很好的文章。

据我所知,一次只能运行一个线程,活动线程每10条指令左右切换一次?

哪里有很好的解释,或者我们可以提供一个?知道在Python中使用线程时遇到的常见问题也将非常高兴。

解决方案

回答

下面是一个基本的线程示例。它将产生20个线程;每个线程将输出其线程号。运行它,并观察其打印顺序。

import threading
class Foo (threading.Thread):
    def __init__(self,x):
        self.__x = x
        threading.Thread.__init__(self)
    def run (self):
          print str(self.__x)

for x in xrange(20):
    Foo(x).start()

正如我们所暗示的那样,Python线程是通过时间切片实现的。这就是他们获得"平行"效果的方式。

在我的示例中,我的Foo类扩展了线程,然后实现了run方法,这是我们要在线程中运行的代码所在的位置。要启动线程,请在线程对象上调用start(),它将自动调用run方法...

当然,这只是最基本的知识。我们最终将想要了解有关信号量,互斥量以及用于线程同步和消息传递的锁的信息。

回答

Python是一种相当容易使用的语言,但是有一些警告。我们需要了解的最大信息是全局解释器锁定。这仅允许一个线程访问解释器。这意味着两件事:1)我们很少在python中使用过lock语句; 2)如果我们想利用多处理器系统,则必须使用单独的进程。编辑:我还应该指出,如果我们也想解决GIL的问题,可以将一些代码放在C / C ++中。

因此,我们需要重新考虑为什么要使用线程。如果要并行化应用程序以利用双核体系结构,则需要考虑将应用程序分解为多个进程。

如果要提高响应速度,则应考虑使用线程。但是,还有其他选择,即微线程。我们还应该研究一些框架:

  • 无堆栈的python
  • 小菜
  • 事态
  • 单片眼镜

回答

是的,由于全局解释器锁定(GIL),一次只能运行一个线程。以下是一些有关此方面的见解的链接:

  • http://www.artima.com/weblogs/viewpost.jsp?thread=214235
  • http://smoothspan.wordpress.com/2007/09/14/guido-is-right-to-leave-the-gil-in-python-not-for-multicore-but-for-utility-computing/

在最后一个链接中有一个有趣的报价:

Let me explain what all that means. 
  Threads run inside the same virtual
  machine, and hence run on the same
  physical machine.  Processes can run
  on the same physical machine or in
  another physical machine.  If you
  architect your application around
  threads, you’ve done nothing to access
  multiple machines.  So, you can scale
  to as many cores are on the single
  machine (which will be quite a few
  over time), but to really reach web
  scales, you’ll need to solve the
  multiple machine problem anyway.

如果要使用多核,则pyprocessing定义一个基于进程的API来进行真正的并行化。 PEP还包括一些有趣的基准。

回答

如果各个工作人员都在进行I / O绑定操作,请在python中使用线程。如果要在计算机上跨多个内核扩展,请为python找到一个好的IPC框架,或者选择其他语言。

回答

尝试记住,GIL设置为经常轮询,以显示多个任务的外观。可以对这个设置进行微调,但是我建议应该进行一些工作,线程正在执行,或者很多上下文切换将导致问题。

我可能会建议在处理器上使用多个父级,并尝试将类似作业保持在同一内核上。