什麼是死鎖,如何避免死鎖(4種方法)

2020-07-16 10:05:07
當兩個執行緒相互等待對方釋放資源時,就會發生死鎖。Python 直譯器沒有監測,也不會主動採取措施來處理死鎖情況,所以在進行多執行緒程式設計時應該採取措施避免出現死鎖。

一旦出現死鎖,整個程式既不會發生任何異常,也不會給出任何提示,只是所有執行緒都處於阻塞狀態,無法繼續。

死鎖是很容易發生的,尤其是在系統中出現多個同步監視器的情況下,如下程式將會出現死鎖:
import threading
import time

class A:
    def __init__(self):
        self.lock = threading.RLock()
    def foo(self, b):
        try:
            self.lock.acquire()
            print("當前執行緒名: " + threading.current_thread().name
                + " 進入了A範例的foo()方法" )     # ①
            time.sleep(0.2)
            print("當前執行緒名: " + threading.current_thread().name
                + " 企圖呼叫B範例的last()方法")   # ③
            b.last()
        finally:
            self.lock.release()
    def last(self):
        try:
            self.lock.acquire()
            print("進入了A類的last()方法內部")
        finally:
            self.lock.release()
class B:
    def __init__(self):
        self.lock = threading.RLock()
    def bar(self, a):
        try:
            self.lock.acquire()
            print("當前執行緒名: " + threading.current_thread().name
                + " 進入了B範例的bar()方法" )   # ②
            time.sleep(0.2)
            print("當前執行緒名: " + threading.current_thread().name
                + " 企圖呼叫A範例的last()方法")  # ④
            a.last()
        finally:
            self.lock.release()
    def last(self):
        try:
            self.lock.acquire()
            print("進入了B類的last()方法內部")
        finally:
            self.lock.release()
a = A()
b = B()
def init():
    threading.current_thread().name = "主執行緒"
    # 呼叫a物件的foo()方法
    a.foo(b)
    print("進入了主執行緒之後")
def action():
    threading.current_thread().name = "副執行緒"
    # 呼叫b物件的bar()方法
    b.bar(a)
    print("進入了副執行緒之後")
# 以action為target啟動新執行緒
threading.Thread(target=action).start()
# 呼叫init()函數
init()
執行上面程式,將會看到如圖 1 所示的效果。

線程死鎖效果
圖 1 死鎖效果