簡體   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