1. 程式人生 > 其它 >Python多執行緒之執行緒鎖

Python多執行緒之執行緒鎖

Threading模組為我們提供了一個類,Threading.Lock鎖。我們建立一個該類物件,線上程函式執行前,“搶佔”該鎖,執行完成後,“釋放”該鎖,則我們確保了每次只有一個執行緒佔有該鎖。這時候對一個公共的物件進行操作,則不會發生執行緒不安全的現象了。

1、我們先建立了一個threading.Lock類物件lock,在run方法裡,我們使用lock.acquire()獲得了這個鎖。此時,其他的執行緒就無法再獲得該鎖了,他們就會阻塞在“if lock.acquire()”這裡,直到鎖被另一個執行緒釋放:lock.release()。

2、如果多個執行緒要呼叫多個現象,而A執行緒呼叫A鎖佔用了A物件,B執行緒呼叫了B鎖佔用了B物件,A執行緒不能呼叫B物件,B執行緒不能呼叫A物件,於是一直等待。這就造成了執行緒“死鎖”。

Threading模組中,也有一個類,RLock,稱之為可重入鎖。該鎖物件內部維護著一個Lock和一個counter物件。counter物件記錄了acquire的次數,使得資源可以被多次require。最後,當所有RLock被release後,其他執行緒才能獲取資源。在同一個執行緒中,RLock.acquire可以被多次呼叫,利用該特性,可以解決部分死鎖問題

3、當多個執行緒同時訪問一個數據時,需加鎖,排隊變成單執行緒一個一個執行

4、加鎖避免併發導致邏輯出錯

5、每當一個執行緒a要訪問共享資料時,必須先獲得鎖定;如果已經有別的執行緒b獲得鎖定了,那麼就讓執行緒a暫停,也就是同步阻塞;等到執行緒b訪問完畢,釋放鎖以後,再讓執行緒a繼續

6、語法

lock=threading.Lock() #建立執行緒鎖

lock = threading.RLock()#建立遞迴鎖(多個鎖時用這個)

lock.acquire() #鎖住

lock.release() 釋放鎖

#未加鎖
'''如果多個執行緒同時操作某個資料,會出現不可預料的結果。比如以下場景:當小夥伴a在往火鍋裡面新增魚丸的時候,小夥伴b在同時吃掉魚丸,這很有可能導致剛下鍋的魚丸被夾出來了(沒有熟),或者還沒下鍋,就去夾魚丸(夾不到)'''
 
 
# coding=utf-8
import threading
import time
def chiHuoGuo(people, do):
    
print("%s 吃火鍋的小夥伴:%s" % (time.ctime(),people)) time.sleep(1) for i in range(3): time.sleep(1) print("%s %s正在 %s 魚丸"% (time.ctime(), people, do)) print("%s 吃火鍋的小夥伴:%s" % (time.ctime(),people)) class myThread (threading.Thread): # 繼承父類threading.Thread def __init__(self, people, name, do): '''重寫threading.Thread初始化內容''' threading.Thread.__init__(self) self.threadName = name self.people = people self.do = do def run(self): # 把要執行的程式碼寫到run函式裡面 執行緒在建立後會直接執行run函式 '''重寫run方法''' print("開始執行緒: " + self.threadName) chiHuoGuo(self.people, self.do) # 執行任務 print("結束執行緒: " + self.name) print("yoyo請小夥伴開始吃火鍋:!!!") # 設定執行緒組 threads = [] # 建立新執行緒 thread1 = myThread("xiaoming", "Thread-1", "新增") thread2 = myThread("xiaowang", "Thread-2", "吃掉") # 新增到執行緒組 threads.append(thread1) threads.append(thread2) # 開啟執行緒 for thread in threads: thread.start() # 阻塞主執行緒,等子執行緒結束 for thread in threads: thread.join() time.sleep(0.1) print("退出主執行緒:吃火鍋結束,結賬走人")
#執行緒鎖,單鎖例項
import time,threading
def run(n):
    lock.acquire() #加鎖
    global num
    num+=1
    lock.release() #釋放鎖
lock=threading.Lock()#獲得執行緒鎖
num=0
threads=[]
for i in range(50):
    thread=threading.Thread(target=run,args=("t-%s"%i,))
    thread.start()
    threads.append(thread)
for i in threads:
    i.join()
print("num:",num)
#執行緒鎖,加鎖例項
 
# coding=utf-8
import threading
import time
def chiHuoGuo(people, do):
    print("%s 吃火鍋的小夥伴:%s" % (time.ctime(),people))
    time.sleep(1)
    for i in range(3):
        time.sleep(1)
        print("%s %s正在 %s 魚丸"% (time.ctime(), people, do))
    print("%s 吃火鍋的小夥伴:%s" % (time.ctime(),people))
class myThread (threading.Thread):   # 繼承父類threading.Thread
    lock = threading.Lock()  # 執行緒鎖
    def __init__(self, people, name, do):
        '''重寫threading.Thread初始化內容'''
        threading.Thread.__init__(self)
        self.threadName = name
        self.people = people
        self.do = do
    def run(self):   # 把要執行的程式碼寫到run函式裡面 執行緒在建立後會直接執行run函式
        '''重寫run方法'''
        print("開始執行緒: " + self.threadName)
        # 執行任務之前鎖定執行緒
        self.lock.acquire()
        chiHuoGuo(self.people, self.do)     # 執行任務
        # 執行完之後,釋放鎖
        self.lock.release()
        print("結束執行緒: " + self.name)
print("yoyo請小夥伴開始吃火鍋:!!!")
# 設定執行緒組
threads = []
# 建立新執行緒
thread1 = myThread("xiaoming", "Thread-1", "新增")
thread2 = myThread("xiaowang", "Thread-2", "吃掉")
# 新增到執行緒組
threads.append(thread1)
threads.append(thread2)
# 開啟執行緒
for thread in threads:
    thread.start()
# 阻塞主執行緒,等子執行緒結束
for thread in threads:
    thread.join()
time.sleep(0.1)
print("退出主執行緒:吃火鍋結束,結賬走人")
#執行緒鎖,多個鎖時,需加遞迴鎖
 
import threading, time
def run1():
    print("grab the first part data")
    lock.acquire()
    global num
    num += 1
    lock.release()
    return num
def run2():
    print("grab the second part data")
    lock.acquire()
    global num2
    num2 += 1
    lock.release()
    return num2
def run3():
    lock.acquire()
    res = run1()
    print('--------between run1 and run2-----')
    res2 = run2()
    lock.release()
    print(res, res2)
num, num2 = 0, 0
lock = threading.RLock() #遞迴鎖
for i in range(3):
    t = threading.Thread(target=run3)
    t.start()
while threading.active_count() != 1:
    print(threading.active_count())
else:
    print('----all threads done---')
    print(num, num2)