天天看點

Python并發程式設計之線程實作方式

作者:風趣生命的起源

在Python中,線程(Thread)是一種輕量級的執行單元,可以并發執行多個線程,每個線程獨立執行任務。線程是作業系統中排程和執行任務的基本機關,它可以與其他線程共享程序的資源和記憶體空間。

Python并發程式設計之線程實作方式

Python線程基本實作

Python提供了内置的`threading`子產品,用于建立和管理線程。使用`threading`子產品可以建立新的線程對象,并通過調用線程對象的`start()`方法來啟動線程的執行。線程對象可以執行任意的可調用對象(如函數、方法等)作為線程的任務,通過定義這些任務可以實作并發執行的功能。

下面是一個簡單的線程示例:

import threading
import time

def print_numbers():
    for i in range(5):
        print(f"Thread 1: {i}")
        time.sleep(1)

def print_letters():
    for letter in "ABCDE":
        print(f"Thread 2: {letter}")
        time.sleep(1)

# 建立線程對象
thread1 = threading.Thread(target=print_numbers)
thread2 = threading.Thread(target=print_letters)

# 啟動線程
thread1.start()
thread2.start()

# 等待線程執行完畢
thread1.join()
thread2.join()

print("Main thread exiting.")           

在上述示例中,我們定義了兩個函數`print_numbers()`和`print_letters()`,分别用于列印數字和字母。然後,我們建立了兩個線程對象`thread1`和`thread2`,并分别指定線程的任務函數。接着,通過調用`start()`方法來啟動線程的執行。最後,使用`join()`方法等待線程執行完畢,確定主線程在所有線程完成後退出。

運作以上代碼,你将看到類似以下的輸出:

Thread 1: 0
Thread 2: A
Thread 1: 1
Thread 2: B
Thread 1: 2
Thread 2: C
Thread 1: 3
Thread 2: D
Thread 1: 4
Thread 2: E
Main thread exiting.           

可以看到,兩個線程交替執行,每個線程執行一次任務後暫停一秒,然後切換到另一個線程執行。這樣就實作了簡單的并發執行。

需要注意的是,線程之間的切換是由作業系統的線程排程器控制的,是以線程的執行順序可能會有不确定性。是以,在使用線程時,需要考慮線程間的同步和互斥,以避免并發通路共享資源導緻的問題。

Python線程同步方式

在Python中,為了保證多線程環境下的線程安全性,可以使用各種同步機制和工具來實作線程間的同步和互斥。下面是幾種常見的Python線程安全同步的方式的示例:

1. 互斥鎖(Lock):

```python

import threading

# 建立互斥鎖對象

import threading

# 建立互斥鎖對象
lock = threading.Lock()

shared_resource = 0

def increment():
    global shared_resource
    for _ in range(100000):
        # 擷取互斥鎖
        lock.acquire()
        shared_resource += 1
        # 釋放互斥鎖
        lock.release()

# 建立多個線程來調用increment函數
threads = []
for _ in range(5):
    t = threading.Thread(target=increment)
    threads.append(t)
    t.start()

# 等待所有線程執行完畢
for t in threads:
    t.join()

print("Result:", shared_resource)           

上述示例中,使用`threading.Lock()`建立了一個互斥鎖對象`lock`。在`increment()`函數中,通過調用`lock.acquire()`擷取互斥鎖,執行臨界區代碼,然後使用`lock.release()`釋放互斥鎖。這樣可以確定每次隻有一個線程可以通路臨界區,進而保證線程安全。

2. 信号量(Semaphore):

import threading

# 建立信号量對象
semaphore = threading.Semaphore(2)

def task():
    # 請求信号量
    semaphore.acquire()
    try:
        # 臨界區代碼
        print("Executing task")
    finally:
        # 釋放信号量
        semaphore.release()

# 建立多個線程來調用task函數
threads = []
for _ in range(5):
    t = threading.Thread(target=task)
    threads.append(t)
    t.start()

# 等待所有線程執行完畢
for t in threads:
    t.join()           

在上述示例中,使用`threading.Semaphore(2)`建立了一個信号量對象`semaphore`,并設定初始值為2。在`task()`函數中,通過調用`semaphore.acquire()`請求信号量,執行臨界區代碼,然後使用`semaphore.release()`釋放信号量。信号量的初始值為2,是以最多允許兩個線程同時進入臨界區,其他線程需要等待。

3. 條件變量(Condition):

import threading

# 建立條件變量對象
condition = threading.Condition()

queue = []

def producer():
    with condition:
        # 生産者線程等待條件滿足
        while len(queue) >= 5:
            condition.wait()
        # 生産者線程向隊列中添加元素
        item = "Item"
        queue.append(item)
        print("Produced:", item)
        # 通知消費者線程
        condition.notify()

def consumer():
    with condition:
        # 消費者線程等待條件滿足
        while len(queue) == 0:
            condition.wait()
        # 消費者線程從隊列中取出元素           

總結

線程是一種用于并發執行任務的執行單元,Python的`threading`子產品提供了建立和管理線程的功能。通過建立線程對象,并指定線程的任務函數,可以實作多個線程的并發執行。但需要注意線程間的同步和互斥,以確定線程安全。