為什麼 Python 中一個執行緒對共享變數所做的變更對其他執行緒不可見?
我嘗試在多個執行緒中使用相同的變量,但該變數的值並未在執行緒之間一致更新。例如,當執行緒 1 將變數更新為 1 時,執行緒 2 無法識別此更改,而是看到舊值。
這是一個說明問題的簡單程式碼範例。當使用者按下“a”鍵時,變數“query”應更新並顯示如下:
- 查詢1:a
- 查詢:a
但是,我得到的實際輸出只是:
- 查詢1:a
您能幫我理解為什麼會發生這種情況以及如何解決它嗎?
import getch import threading QUERY = "" EXIT_THREAD = False def input_thread(): global EXIT_THREAD last_query = "" while not EXIT_THREAD: if last_query != QUERY: last_query = QUERY print(f"Query: {QUERY}") thread = threading.Thread(target=input_thread) thread.start() while True: char = getch.getch() if char == "\n": break elif char == "\x7f": QUERY = QUERY[:-1] else: QUERY += char print(f"Query1: {QUERY}") # kill input thread EXIT_THREAD = True thread.join()
正確答案
問題是 getch
模組編碼很差。當它阻塞等待輸入時,它不會釋放gil(全域解釋器鎖定),因此您的其他執行緒不允許運行。與鎖定同步並沒有多大幫助; gil 已保護對 query
的存取。
問題是,每次更改 query
後,您都會回到 getch
,這會鎖定 gil。當getch
返回時,已經過去了足夠的時間,gil 立即被移交,另一個線程檢查更改,看到最後的更改並報告它,主線程最終得到返回控制權,但通常在getch
再次鎖定它之前沒有做足夠的事情來導致另一次gil 切換,並且另一個線程永遠沒有機會運行並看到更改,直到getch
下次返回。這可能會因 python 版本的不同而有所不同(檢查 gil 的規則會不時發生變化),但它總是不穩定。
正確的解決方案是getch
模組在進行阻塞呼叫之前在內部釋放gil,但如果做不到這一點,您可以透過在每個getch
之前故意以gil 釋放方式阻塞來給其他執行緒一些執行時間呼叫時,透過匯入time
模組,並加入一個sleep 來給其他執行緒時間來查看最新的變更:
while True: time.sleep(0.001) # Explicitly releases GIL for a millisecond char = getch.getch()
這會得到您期望的行為,雖然從技術上講,如果涉及其他線程,則會受到競爭條件的影響,但對於像這樣的兩個線程來說,它是相當可靠的。
以上是為什麼 Python 中一個執行緒對共享變數所做的變更對其他執行緒不可見?的詳細內容。更多資訊請關注PHP中文網其他相關文章!

熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

AI Hentai Generator
免費產生 AI 無盡。

熱門文章

熱工具

記事本++7.3.1
好用且免費的程式碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強大的PHP整合開發環境

Dreamweaver CS6
視覺化網頁開發工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

熱門話題

Linux終端中查看Python版本時遇到權限問題的解決方法當你在Linux終端中嘗試查看Python的版本時,輸入python...

如何在10小時內教計算機小白編程基礎?如果你只有10個小時來教計算機小白一些編程知識,你會選擇教些什麼�...

在使用Python的pandas庫時,如何在兩個結構不同的DataFrame之間進行整列複製是一個常見的問題。假設我們有兩個Dat...

使用FiddlerEverywhere進行中間人讀取時如何避免被檢測到當你使用FiddlerEverywhere...

Uvicorn是如何持續監聽HTTP請求的? Uvicorn是一個基於ASGI的輕量級Web服務器,其核心功能之一便是監聽HTTP請求並進�...

本文討論了諸如Numpy,Pandas,Matplotlib,Scikit-Learn,Tensorflow,Tensorflow,Django,Blask和請求等流行的Python庫,並詳細介紹了它們在科學計算,數據分析,可視化,機器學習,網絡開發和H中的用途

在Python中,如何通過字符串動態創建對象並調用其方法?這是一個常見的編程需求,尤其在需要根據配置或運行...
