需要帮助了解 python 线程风格

Need help understanding python threading flavors

我现在很喜欢线程并探索线程和线程库。当我开始使用它们时,我编写了 2 个基本程序。以下是 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"[=38= 相比 higher-class library ]。而我进入 thread_1.py 的 AttributeError 是因为我在从线程库启动的线程上运行而不是线程。

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

简短回答:忽略 thread module and just use threading

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

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

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

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

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

回答你的具体问题:如果你必须直接使用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 中:这正是 threading 模块的要点:它提供了丰富、易于使用的 API 代替最小的、难以使用的 thread API。所以我们回到总结行:不要使用 thread,使用 threading.