Python Threading 學習筆記 | 6、鎖lock

  • 2019 年 11 月 7 日
  • 筆記

0x00 關於執行緒鎖lock

多執行緒和多進程最大的不同在於,多進程中,同一個變數,各自有一份拷貝存在於每個進程中,互不影響,而多執行緒中,所有變數都由所有執行緒共享,所以,任何一個變數都可以被任何一個執行緒修改,因此,執行緒之間共享數據最大的危險在於多個執行緒同時改一個變數,把內容給改亂了。

而使用lock就可以在不同執行緒使用同一共享記憶體時,能夠確保執行緒之間互不影響。

0x01 不使用lock鎖的情況

job1:全局變數A的值每次加1,循環7次並列印

def job1(): # 全局變數A的值每次加1,循環7次並列印     global A     for i in range(7):        A += 1        print('job1',A)

job2:全局變數A的值每次加10,循環7次並列印

def job2():# 全局變數A的值每次加10,循環7次並列印     global A     for i in range(7):        A += 10        print('job2',A)

main:定義兩個執行緒並執行job1和job2

def main(): # 定義兩個執行緒並執行job1和job2     t1 = threading.Thread(target=job1)     t2 = threading.Thread(target=job2)     t1.start()     t2.start()     t1.join()     t2.join()

完整程式碼:

import threading      def job1(): # 全局變數A的值每次加1,循環7次並列印     global A     for i in range(7):        A += 1        print('job1',A)      def job2():# 全局變數A的值每次加10,循環7次並列印     global A     for i in range(7):        A += 10        print('job2',A)      def main(): # 定義兩個執行緒並執行job1和job2     t1 = threading.Thread(target=job1)     t2 = threading.Thread(target=job2)     t1.start()     t2.start()     t1.join()     t2.join()      if __name__ == '__main__':     A = 0     main()

運行結果:

# python 6_lock.py  job1 1  job1 2  job1 3  job1 4  job1 5job2 15  job2  job1 2625  job2  job1 36 37  job2  47  job2 57  job2 67  job2 77

可以看到不使用lock的時候,列印的結果很混亂。

0x02 使用lock的情況

使用lock的方法是, 在每個執行緒執行運算修改共享記憶體之前,執行lock.acquire()將共享記憶體上鎖, 確保當前執行緒執行時,記憶體不會被其他執行緒訪問,執行運算完畢後,使用lock.release()將鎖打開, 保證其他的執行緒可以使用該共享記憶體。

為job1和job2加鎖:

def job1(): # 全局變數A的值每次加1,循環7次並列印     global A,lock     lock.acquire() # 上鎖     for i in range(7):        A += 1        print('job1',A)     lock.release() # 開鎖      def job2():# 全局變數A的值每次加10,循環7次並列印     global A,lock     lock.acquire() # 上鎖     for i in range(7):        A += 10        print('job2',A)     lock.release() # 開鎖

在程式入口處定義一個lock

if __name__ == '__main__':     lock = threading.Lock()     A = 0     main()

完整程式碼:

import threading      def job1(): # 全局變數A的值每次加1,循環7次並列印     global A,lock     lock.acquire()     for i in range(7):        A += 1        print('job1',A)     lock.release()      def job2():# 全局變數A的值每次加10,循環7次並列印     global A,lock     lock.acquire()     for i in range(7):        A += 10        print('job2',A)     lock.release()      def main(): # 定義兩個執行緒並執行job1和job2     t1 = threading.Thread(target=job1)     t2 = threading.Thread(target=job2)     t1.start()     t2.start()     t1.join()     t2.join()      if __name__ == '__main__':     lock = threading.Lock()     A = 0     main()

運行結果:

# python 6_lock.py  job1 1  job1 2  job1 3  job1 4  job1 5  job1 6  job1 7  job2 17  job2 27  job2 37  job2 47  job2 57  job2 67  job2 77

從運行結果來看,使用lock後,一個執行緒一個執行緒的執行完,兩個執行緒之間互不影響。

至此,整個【Python Threading 學習筆記】系列更新完畢。

原文地址:https://www.teamssix.com/year/191105-121011.html 程式碼項目地址:https://github.com/teamssix/Python-Threading-study-notes 參考文章: 1、https://www.jianshu.com/p/05b6a6f6fdac 2、https://morvanzhou.github.io/tutorials/python-basic/threading