繁体   English   中英

同一个回调,多线程

[英]Same callback, multiple threads

如果我创建多个线程并将相同的回调传递给所有线程,这些线程是否会同时执行 memory 的同一块(相同的函数/回调)? 线程回调是按值传递还是按引用传递? 这是一个依赖于语言的功能吗? 由于全局解释器锁定与诸如 C# 之类的语言,这将如何在 Python 中工作?

下面的代码显示了正在打印的不同线程 ID,但是 function 位置呢? 是否有 LongOperation 的副本,或者每个线程在每次运行其代码时都访问相同的 memory 位置?

python 中的示例代码:

def LongOperation():
    print( "Spinning up a thread with this ID: " + str(threading.get_ident()))
    print("Finishing up thread ID: " + str(threading.get_ident()))

i = 0
while i < 10:
    threading.Thread(target=LongOperation).start()
    i = i + 1

谢谢阅读。

函数被编译成代码对象。 LongOperation是一个引用这些代码块之一的变量。 每次调用LongOperation时,python 都会创建一个框架 object,该框架将保存对该单个调用唯一的局部变量。 尽管框架 object 将被视为“通过引用调用”,因为每次调用都会创建一个唯一的框架,但没有其他 function 会引用它。 例外情况是,如果您的 function 有yield 然后你有一个可以传递给许多其他函数的生成器。

在您的情况下,每个线程访问相同的 function object 的代码,但单独的框架对象的数据。 这与 C 非常相似,其中许多调用者将获得相同的代码但不同的数据堆栈帧。

CPython 仅在线程获取 GIL 时执行字节码。 它将定期释放 GIL 以让线程交错,但一次只能执行一个。 Python 扩展(在 python 的标准库中 - 例如,正则表达式,或外部,例如,numpy)如果愿意,可以自由释放 GIL。 它不是必需的,何时发布 GIL 是一种个人意见。 CPython 在执行诸如读取文件之类的阻塞操作时也会释放 GIL。

如果你有纯 python 不使用释放 GIL 的扩展并且不做 I/O,多线程并不比顺序做事快。 但是,如果您的代码执行这些操作,多线程可能会有所帮助。

Python 的异步支持非常适合处理文件系统或网络访问等阻塞问题。 它自然地扩展到完全将 1 个 cpu 提交给您的程序,而无需在更传统的程序中管理多个线程的复杂性。

如果您使用释放 GIL 的 package 进行大型数值处理,那么多线程会再次变得有趣,因为您的程序可以消耗多个 CPU。

  • 如果我创建多个线程并将相同的回调传递给所有线程,这些线程是否会同时执行 memory 的同一块(相同的函数/回调)?

    是的,它们使用相同的程序代码

  • 线程回调是按值传递还是按引用传递?

    每个线程都可以有它的局部变量

  • 这是一个依赖于语言的功能吗?

    不确定,但我认为是的。

  • 由于全局解释器锁定与诸如 C# 之类的语言,这将如何在 Python 中工作?

    我认为它与 GIL 无关,您仍然可以使用多线程 Python 进行高度 IO(不是 CPU)工作。

对于您的代码,我对此进行了测试:

import threading
import time

def LongOperation(i):
    print("Spinning up a thread with this ID: " + str(threading.currentThread()))
    print("Finishing up thread ID: " + str(threading.currentThread().ident))
    print("Input data_index: " + str(i))

i = 0
while i < 5:
    threading.Thread(target=LongOperation, args=(i,)).start()
    i = i + 1

Output:

Spinning up a thread with this ID: <Thread(Thread-1, started 123145548488704)>
Finishing up thread ID: 123145548488704
Spinning up a thread with this ID: <Thread(Thread-2, started 123145552695296)>
Finishing up thread ID: 123145552695296Input data_index: 0

Input data_index: 1
Spinning up a thread with this ID: <Thread(Thread-3, started 123145548488704)>
Finishing up thread ID: 123145548488704
Input data_index: 2
Spinning up a thread with this ID: <Thread(Thread-4, started 123145552695296)>
Finishing up thread ID: 123145552695296
Input data_index: 3

Spinning up a thread with this ID: <Thread(Thread-5, started 123145556901888)>
Finishing up thread ID: 123145556901888
Input data_index: 4

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM