python - 需要帮助了解 python 线程风格

标签 python multithreading python-multithreading

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

线程_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

线程_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 一样,其中交错打印使其成为线程执行的令人信服的示例。我的理解是,与“线程”相比,“线程”是一个更高级别的库。我在 thread_1.py 中得到的 AttributeError 是因为我在从线程库启动的线程上操作,而不是线程。

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

最佳答案

简短回答:忽略 thread 模块,只需使用 threading .
threadthreading模块服务于完全不同的目的。 thread module 是一个用 C 编写的低级模块,旨在抽象出平台差异并提供一个最小的跨平台基元集(本质上是线程和简单的锁),可以作为高级 API 的基础。如果您将 Python 移植到不支持现有线程 API(例如 POSIX 线程)的新平台,那么您必须编辑 thread模块源,以便您可以包装适当的操作系统级调用以在新平台上提供相同的原语。

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

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

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

关于python - 需要帮助了解 python 线程风格,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35526578/

相关文章:

multithreading - 什么是多线程该做和不该做的事情?

Python:如何在每次输出而不是终止时获取子进程的输出?

python - 将此程序中所有可能路径返回到嵌套列表的算法

python - 如何在 peewee 中创建自引用的多对多字段?

c# - IronPython/C# 脚本运行后无法重新打开串行端口

java - 当线程被本质锁阻塞时执行代码

Python:Tkinter 中的 after() 是否具有多线程方法?

python - 每 N 秒在后台线程中重复执行一个函数

android - 将 .pb 转换为 .tflite 时反量化的自定义实现

python - 尝试使用 aws ses 发送电子邮件并将 zip 文件作为附件附加