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