天天看點

線程互斥鎖 Lock前言Python 線程互斥鎖Python 線程死鎖重點總結

線程互斥鎖 Lock

  • 前言
  • Python 線程互斥鎖
    • 1.建立互斥鎖
    • 鎖定資源/解鎖資源
  • Python 線程死鎖
    • 1.引入庫
  • 重點總結

前言

Python 線程互斥鎖

1.建立互斥鎖

# 導入線程threading子產品
import threading

# 建立互斥鎖
mutex = threading.Lock()
           

鎖定資源/解鎖資源

# 導入線程threading子產品
import threading

# 聲明全局變量
g_num = 0
# 建立互斥鎖
mutex = threading.Lock()

def my_thread1():

    # 聲明全局變量
    global g_num
    # 循環 1000000 次,每次累計加 1
    for i in range(0,1000000):
        # 鎖定資源
        mutex.acquire()
        g_num = g_num + 1
        # 解鎖資源
        mutex.release()

def my_thread2():

    # 聲明全局變量
    global g_num
    # 循環 1000000 次,每次累計加 1
    for i in range(0,1000000):
        # 鎖定資源
        mutex.acquire()
        g_num = g_num + 1
        # 解鎖資源
        mutex.release()

def main(i):

    # 聲明全局變量
    global g_num
    # 初始化全局變量,初始值為 0
    g_num = 0
    # 建立兩個線程,對全局變量進行累計加 1
    t1 = threading.Thread(target=my_thread1)
    t2 = threading.Thread(target=my_thread2)

    # 啟動線程
    t1.start()
    t2.start()
    # 阻塞函數,等待線程結束
    t1.join()
    t2.join()
    # 擷取全局變量的值
    print("第%d次計算結果:%d "% (i,g_num))

if __name__ == "__main__":

    # 循環4次,調用main函數,計算全局變量的值
    for i in range(1,5):
        main(i)

'''
輸出結果:

第1次計算結果:2000000 
第2次計算結果:2000000 
第3次計算結果:2000000 
第4次計算結果:2000000
'''
           

注意:互斥鎖一旦鎖定之後要記得解鎖,否則資源會一直處于鎖定狀态;

Python 線程死鎖

1.引入庫

1.單個互斥鎖的死鎖:acquire / release 是成對出現的,互斥鎖對資源鎖定之後就一定要解鎖,否則資源會一直處于鎖定狀态,其他線程無法修改;任何一個線程沒有釋放資源 release,程式就會一直處于阻塞狀态(在等待資源被釋放)

2.多個互斥鎖的死鎖:在同時操作多個互斥鎖的時候一定要格外小心,因為一不小心就容易進入死循環。

# 導入線程threading子產品
import threading
# 導入線程time子產品
import time


# 建立互斥鎖
mutex_one = threading.Lock()
mutex_two = threading.Lock()

def programmer_thread1():

    mutex_one.acquire()
    print("我是程式員1,module1開發正式開始,誰也别動我的代碼")
    time.sleep(2)

    # 此時會堵塞,因為這個mutex_two已經被線程programmer_thread2搶先上鎖了,等待解鎖
    mutex_two.acquire()
    print("等待程式員2通知我合并代碼")
    mutex_two.release()

    mutex_one.release()

def programmer_thread2():
    mutex_two.acquire()
    print("我是程式員2,module2開發正式開始,誰也别動我的代碼")
    time.sleep(2)

    # 此時會堵塞,因為這個mutex_one已經被線程programmer_thread1搶先上鎖了,等待解鎖
    mutex_one.acquire()
    print("等待程式員1通知我合并代碼")
    mutex_one.release()

    mutex_two.release()

def main():

    t1 = threading.Thread(target=programmer_thread1)
    t2 = threading.Thread(target=programmer_thread2)

    # 啟動線程
    t1.start()
    t2.start()
    # 阻塞函數,等待線程結束
    t1.join()
    t2.join()
    # 整合代碼結束
    print("整合代碼結束 ")

if __name__ == "__main__":

    main()

'''
輸出結果:

我是程式員1,module1開發正式開始,誰也别動我的代碼
我是程式員2,module2開發正式開始,誰也别動我的代碼
'''
           

分析:程式員 1 在等程式員 2 通知,程式員 2 在等程式員 1 通知,兩個線程都陷入阻塞中,因為兩個線程都在等待對方解鎖,這就是死鎖!是以在開發中對于死鎖的問題還是需要多多注意!

重點總結

1.線程與線程之間共享全局變量需要設定互斥鎖;

2.注意在互斥鎖操作中 acquire / release 成對出現,并且保證上鎖後一定要記得解鎖,避免造成死鎖;