[英]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.