文章

第27天:多線程與多進程

課程簡介

在 Python 中,為了提升程式的運行效率,特別是針對 I/O 密集型和 CPU 密集型任務,可以使用多線程與多進程來進行並行或並發處理。今天的課程將介紹 Python 中的多線程和多進程概念,並學習如何使用標準庫中的 threadingmultiprocessing 模組。


學習內容

1. 多線程(Multithreading)

多線程適用於 I/O 密集型任務,例如檔案讀寫、網絡請求等。Python 提供了 threading 模組來實現多線程。

1.1 創建線程

可以使用 threading.Thread 類來創建一個新線程。

範例:

1
2
3
4
5
6
7
8
9
10
11
12
13
import threading
import time

# 定義一個任務函數
def task():
    print("任務開始")
    time.sleep(2)
    print("任務結束")

# 創建並啟動線程
thread = threading.Thread(target=task)
thread.start()
thread.join()  # 等待線程執行完畢

1.2 使用多個線程

可以同時創建多個線程來執行任務。

範例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 定義任務
def print_numbers():
    for i in range(5):
        print(i)
        time.sleep(1)

# 創建多個線程
threads = [threading.Thread(target=print_numbers) for _ in range(3)]

# 啟動並等待所有線程完成
for t in threads:
    t.start()
for t in threads:
    t.join()

1.3 使用鎖(Lock)

當多個線程需要訪問共享資源時,為避免資源競爭,應使用鎖來確保執行的安全性。

範例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
lock = threading.Lock()
counter = 0

def increase():
    global counter
    with lock:  # 使用鎖
        local_counter = counter
        time.sleep(0.1)
        counter = local_counter + 1
    print(counter)

# 創建並啟動線程
threads = [threading.Thread(target=increase) for _ in range(5)]
for t in threads:
    t.start()
for t in threads:
    t.join()

2. 多進程(Multiprocessing)

多進程適用於 CPU 密集型任務,例如大量的數據計算。Python 的 multiprocessing 模組可以創建多個進程來分配不同的 CPU 核心。

2.1 創建進程

使用 multiprocessing.Process 類創建一個新進程。

範例:

1
2
3
4
5
6
7
8
9
10
11
from multiprocessing import Process

def process_task():
    print("進程開始")
    time.sleep(2)
    print("進程結束")

# 創建並啟動進程
process = Process(target=process_task)
process.start()
process.join()  # 等待進程完成

2.2 使用多個進程

可以創建多個進程來並行執行不同的任務。

範例:

1
2
3
4
5
6
7
8
9
10
11
12
# 定義任務
def calculate_square(n):
    print(f"{n} 的平方為 {n ** 2}")

# 創建多個進程
processes = [Process(target=calculate_square, args=(i,)) for i in range(5)]

# 啟動並等待所有進程完成
for p in processes:
    p.start()
for p in processes:
    p.join()

2.3 使用進程池(Pool)

當需要大量進程時,可以使用進程池來管理進程並限制同時運行的進程數。

範例:

1
2
3
4
5
6
7
8
from multiprocessing import Pool

def cube(n):
    return n ** 3

with Pool(3) as pool:  # 同時執行 3 個進程
    results = pool.map(cube, range(10))
    print(results)

3. 多線程與多進程的選擇

  • I/O 密集型任務:多線程適用於需要頻繁進行 I/O 操作的任務,如讀取檔案、處理網絡請求。
  • CPU 密集型任務:多進程適用於需要大量計算的任務,可充分利用多核心處理器。

4. GIL(全局解釋器鎖)

Python 的 GIL 限制了多線程在同一時間只能有一個線程執行 Python bytecode,因此多線程不適合 CPU 密集型任務。而多進程不受 GIL 限制,適合 CPU 密集型任務。


教學重點

  • 多線程的基本操作:理解如何使用 threading 創建與管理線程,以及鎖的使用。
  • 多進程的基本操作:掌握如何使用 multiprocessing 創建與管理進程,並利用進程池來優化多進程處理。
  • 多線程 vs. 多進程的選擇:理解 GIL 的影響,並選擇適合的並行方式。
  • 資源同步:使用鎖來管理多線程間的共享資源,避免競爭條件。

任務

  1. 使用多線程模擬一個同時處理多個檔案的 I/O 任務。
  2. 使用多進程計算 1 到 10 的平方並顯示結果。
  3. 創建一個進程池來並行處理多個數字的立方計算。
本文章以 CC BY 4.0 授權