Python 多線程(Multithreading)是一種允許程序並發執行多個線程的技術,每個線程可以獨立完成任務。這在需要執行 I/O 密集型任務(如文件讀寫、網絡請求等)時非常有用,因為線程可以在等待外部資源的同時執行其他操作。
Python 提供了內置的 threading
模塊來支持多線程操作,這使得可以在程序中同時運行多個任務。
threading
模塊的基本用法threading
模塊允許你創建並管理線程。常見的操作有:
可以通過 threading.Thread()
來創建一個線程,並通過 start()
方法來啟動它。
import threading
def task():
print("這是一個子線程的任務")
# 創建線程
thread = threading.Thread(target=task)
# 啟動線程
thread.start()
# 等待線程完成
thread.join()
print("主線程結束")
輸出:
這是一個子線程的任務
主線程結束
target
:指定線程要執行的函數。start()
:啟動線程,這將使線程進入就緒狀態,等待 CPU 調度。join()
:讓主線程等待子線程完成後再繼續執行。當線程執行的任務需要參數時,可以使用 args
參數來傳遞。
import threading
def task(name, delay):
print(f"{name} 線程啟動,延遲 {delay} 秒")
# 創建多個線程
thread1 = threading.Thread(target=task, args=("Thread-1", 2))
thread2 = threading.Thread(target=task, args=("Thread-2", 3))
# 啟動線程
thread1.start()
thread2.start()
# 等待線程完成
thread1.join()
thread2.join()
print("主線程結束")
輸出:
Thread-1 線程啟動,延遲 2 秒
Thread-2 線程啟動,延遲 3 秒
主線程結束
Thread
類來創建線程除了使用 target
來指定線程執行的函數外,也可以通過繼承 threading.Thread
類來創建線程,這樣可以更加靈活地管理線程的行為。
import threading
class MyThread(threading.Thread):
def __init__(self, name, delay):
super().__init__()
self.name = name
self.delay = delay
def run(self):
print(f"{self.name} 線程啟動,延遲 {self.delay} 秒")
# 創建線程對象
thread1 = MyThread("Thread-1", 2)
thread2 = MyThread("Thread-2", 3)
# 啟動線程
thread1.start()
thread2.start()
# 等待線程完成
thread1.join()
thread2.join()
print("主線程結束")
輸出:
Thread-1 線程啟動,延遲 2 秒
Thread-2 線程啟動,延遲 3 秒
主線程結束
在這個例子中,我們通過繼承 threading.Thread
類來創建自己的線程類,並重寫了 run()
方法,當線程啟動時,會自動執行 run()
內的邏輯。
在多線程編程中,當多個線程需要同時讀寫共享數據時,可能會導致競爭條件(Race Condition)問題。為了防止多個線程同時訪問或修改共享資源,通常會使用「鎖」(Lock)進行同步。
Lock
同步線程threading.Lock
是 Python 中用來實現線程同步的基本工具。鎖保證了在同一時刻,只有一個線程可以訪問共享資源。
import threading
lock = threading.Lock()
shared_resource = 0
def task():
global shared_resource
for _ in range(1000000):
with lock: # 獲取鎖
shared_resource += 1
# 創建多個線程
threads = []
for i in range(5):
thread = threading.Thread(target=task)
threads.append(thread)
thread.start()
# 等待所有線程完成
for thread in threads:
thread.join()
print(f"共享資源的最終值: {shared_resource}")
在這個例子中,我們使用 lock
來保證每次只有一個線程能修改 shared_resource
。這避免了競爭條件導致的錯誤數據。
RLock
來實現可重入鎖有時候,鎖需要在同一個線程中被多次獲取,此時可以使用 threading.RLock
,它是一種可重入鎖。
import threading
rlock = threading.RLock()
def task():
with rlock:
print("第一次獲取鎖")
with rlock:
print("第二次獲取鎖")
thread = threading.Thread(target=task)
thread.start()
thread.join()
輸出:
第一次獲取鎖
第二次獲取鎖
Semaphore
Semaphore
允許一定數量的線程同時訪問共享資源,而不是只有一個。這在控制併發數量時非常有用。
import threading
import time
semaphore = threading.Semaphore(3)
def task(name):
with semaphore:
print(f"{name} 獲取了資源")
time.sleep(2)
print(f"{name} 釋放了資源")
# 創建多個線程
threads = []
for i in range(5):
thread = threading.Thread(target=task, args=(f"Thread-{i+1}",))
threads.append(thread)
thread.start()
# 等待所有線程完成
for thread in threads:
thread.join()
這裡的 Semaphore(3)
限制最多只能有 3 個線程同時獲取資源。
Event
Event
是一個用來實現線程間通信的同步工具,線程可以等待某個事件發生。
import threading
import time
event = threading.Event()
def task():
print("線程等待事件觸發")
event.wait() # 等待事件觸發
print("事件已觸發,繼續執行")
thread = threading.Thread(target=task)
thread.start()
time.sleep(2)
print("觸發事件")
event.set() # 觸發事件
輸出:
線程等待事件觸發
觸發事件
事件已觸發,繼續執行