iT邦幫忙

0

用排隊上廁所來比喻Python Thread的Lock機制!

Python MultiThread多線程中的Lock用途?

Lock機制通常會使用於,當有多個線程要使用同一個代碼資源,且對同一個全域(共享)變數進行修改的時候。
例如當有多個線程要使用同一段程式碼資源時,若不想要在使用期間被其他線程拿來同時使用,此時就可以用 鎖(Lock) 的機制來確保資源一次只給一個線程運行。

用排隊上廁所來比喻吧!

假如今天有一間廁所(function)和一把鑰匙(threading.Lock()),有很多的人(threads)都在排隊要大號,先到的人(thread)就可以獲得廁所門的鑰匙(lock),並且在上廁所的時候會把門鎖起來(lock.acquire()),此時正在排隊的其他人就只能在門外等待,直到正在大號的人把門打開將鑰匙交出來(lock.release()),這樣下一個人就能拿到這鑰匙進入廁所,並把門鎖起來以防止他人進入,以此類推~
img

如何使用Lock?

創建一個lock對象: lock = threading.Lock()
獲取使用lock: lock.acquire()
解除釋放lock: lock.release()

程式碼範例:

import threading
import time

lock = threading.Lock()  # 廁所門的鑰匙(lock)
toilet = []  # 放屎的馬桶(list)

# 廁所(function)
def WC():
    lock.acquire()  # 使用鑰匙將廁所門上鎖

    toilet.append(f"{threading.current_thread().name}: 拉了第1坨屎")  # 將當前的人(線程)所拉的第一屎放進馬桶(list)中
    time.sleep(0.1)
    toilet.append(f"{threading.current_thread().name}: 拉了第2坨屎")  # 將當前的人(線程)所拉的第二屎放進馬桶(list)中

    lock.release()  # 將廁所門解鎖, 並把鑰匙放在旁邊等下一個人來拿


# 產生3位排隊大號的人
for i in range(3):
    wc_thread = threading.Thread(target=WC)
    wc_thread.start()  # 第 i 個人開始進廁所大號

time.sleep(1)  # 等待一秒確保三個人都上完廁所, 且馬桶內都有他們排放的屎了
print(toilet)  # 將馬桶內的屎打印出來看排序

輸出結果:

使用Lock:

['Thread-1: 拉了第1坨屎', 'Thread-1: 拉了第2坨屎', 'Thread-2: 拉了第1坨屎', 'Thread-2: 拉了第2坨屎', 'Thread-3: 拉了第1坨屎', 'Thread-3: 拉了第2坨屎']

不使用Lock:

['Thread-1: 拉了第1坨屎', 'Thread-2: 拉了第1坨屎', 'Thread-3: 拉了第1坨屎', 'Thread-1: 拉了第2坨屎', 'Thread-3: 拉了第2坨屎', 'Thread-2: 拉了第2坨屎']

由此可知,有使用Lock的馬桶(list)結果會是:
先等第一個人(Thread-1)拉完兩坨屎後,第二位(Thread-2)和第三位(Thread-3)才會接續繼續。

反之,不使用Lock的馬桶(list)結果會是:
第一個人(Thread-1)才剛拉完第一坨屎,都還沒拉完第二坨,第二位(Thread-2)和第三位(Thread-3)就一起進來各拉了第一坨屎,後續也一起拉了第二坨,等於現在這間廁所內同時有三個人在拉屎。

結論:

當有多個執行緒同時執行lock.acquire()時,只有一個執行緒能成功獲取到鎖,並且繼續執行程式碼,其他的執行緒就只能等待直到鎖被釋放並獲得為止。


尚未有邦友留言

立即登入留言