需要帮助了解python线程风格

时间:2016-02-20 17:26:06

标签: python multithreading python-multithreading

我现在进入线程并探索线程和线程库。当我开始使用它们时,我写了两个基本程序。以下是2个程序及其相应的输出:

threading_1.py:

import threading

def main():
    t1=threading.Thread(target=prints,args=(3,))
    t2=threading.Thread(target=prints,args=(5,))
    t1.start()
    t2.start()
    t1.join()
    t2.join()

def prints(i):
    while(i>0):
        print "i="+str(i)+"\n"
        i=i-1

if __name__=='__main__':
    main()

输出:

i=3

i=2
i=5


i=4
i=1


i=3

i=2

i=1

thread_1.py

import thread
import threading

def main():
    t1=thread.start_new_thread(prints,(3,))
    t2=thread.start_new_thread(prints,(5,))
    t1.start()
    t2.start()
    t1.join()
    t2.join()

def prints(i):
    while(i>0):
        print "i="+str(i)+"\n"
        i=i-1

if __name__=='__main__':
   main()

输出:

Traceback (most recent call last):
i=3
  File "thread_1.py", line 19, in <module>

    i=2

i=1
main()

i=5

i=4

i=3

i=2

i=1

  File "thread_1.py", line 8, in main
    t1.start()
AttributeError: 'int' object has no attribute 'start'

我想要的输出与threading_1.py一样,其中交错打印使其成为线程执行的令人信服的示例。我的理解是“threading”是一个更高级的库“thread”相比。我在thread_1.py中得到的 AttributeError 是因为我在一个从线程库开始而不是线程的线程上运行。

所以,现在我的问题是 - 如何使用thread_1.py实现类似于threading_1.py输出的输出。可以修改或调整程序以产生相同的结果吗?

1 个答案:

答案 0 :(得分:1)

简短回答:忽略thread模块,然后使用threading

threadthreading模块的用途完全不同。 thread模块是一个用C语言编写的低级模块,旨在抽象出平台差异并提供一个最小跨平台原语集(基本上是线程和简单锁)作为更高级API的基础。如果您将Python移植到不支持现有线程API的新平台(例如POSIX线程),那么您必须编辑thread模块源,以便可以包装适当的OS-级别调用在您的新平台上提供相同的原语。

作为一个例子,如果你看一下当前的CPython实现,你会发现Python Lock基于Linux上的未命名POSIX信号量,基于POSIX条件变量和POSIX互斥量的组合。 OS X(不支持未命名的信号量),以及Event和Windows特定的库调用集合,在Windows上提供各种原子操作。作为Python用户,您不必关心这些细节。 thread模块提供了抽象层,使您可以构建更高级别的代码,而无需担心平台级别的详细信息。

因此,thread模块实际上是为那些开发Python而不是那些使用它的人提供便利:它不是普通Python用户需要处理的东西。出于这个原因,该模块已在Python 3中重命名为_thread:前导下划线表示它是私有的,并且用户不应该依赖其API或行为。

相比之下,threading - 模块是一个用Python编写的Java启发模块。它建立在thread模块奠定的基础之上,为启动和加入线程提供了方便的API,以及一组广泛的并发原语(可重入锁,事件,条件变量,信号量,障碍等)对于用户。这几乎总是您作为Python用户想要使用的模块。如果您对幕后发生的事情感兴趣,那么值得花些时间查看threading source:您可以看到threading模块如何从{{1}中获取所需的原语模块并将所有内容放在一起以提供更高级别的API。

请注意,从Python核心开发人员的角度来看,这里有不同的权衡。一方面,将Python移植到新平台应该很容易,因此thread模块应该很小:您只需要实现一些基本原语来启动并运行在新平台上。相比之下,Python 用户需要各种各样的并发原语,因此thread库需要广泛来支持这些用户的需求。将线程功能拆分为两个单独的层是提供用户需求的一种好方法,同时不会使在各种平台上维护Python变得不必要。

要回答您的具体问题:如果您必须直接使用threading库(尽管我上面已经说过),您可以这样做:

thread

但是当然,使用import thread import time def main(): t1=thread.start_new_thread(prints,(3,)) t2=thread.start_new_thread(prints,(5,)) def prints(i): while(i>0): print "i="+str(i)+"\n" i=i-1 if __name__=='__main__': main() # Give time for the output to show up. time.sleep(1.0) 是处理主线程中的事情的一种非常伪劣的方式:实际上,我们希望等到两个子线程在退出之前完成它们的工作。所以我们需要构建一些主线程可以等待子线程的功能。该功能并不直接存在于time.sleep模块中,而是存在于thread中:这正是threading模块的要点:它提供了丰富易用的API取代最小的,难以使用的threading API。我们回到摘要栏:不要使用thread,请使用thread