鎖的分類 :
線程安全:
線程池:
生產(chǎn)者消費(fèi)者模型:
'''
鎖:由于線程之間隨機(jī)調(diào)度:某線程可能在執(zhí)行n條后,CPU接著執(zhí)行其他線程。為了多個線程同時操作一個內(nèi)存中的資源時不產(chǎn)生混亂,我們使用鎖。 為什么加鎖:1、用于非線程安全, 2、控制一段代碼,確保其不產(chǎn)生調(diào)度混亂。
鎖種類介紹: 1、Lock(指令鎖)是可用的最低級的同步指令。Lock處于鎖定狀態(tài)時,不被其他的線程擁有。
# import threading # import time # # v = [] # lock = threading.Lock() # # def func(arg): # lock.acquire() #獲得鎖定 # v.append(arg) # time.sleep(0.01) # m = v[-1] # print(arg,m) # lock.release() #釋放鎖定 # # # for i in range(10): # t =threading.Thread(target=func,args=(i,)) # t.start()
2、RLockRLock(可重入鎖)是一個可以被同一個線程請求多次的同步指令。RLock使用了“擁有的線程”和“遞歸等級”的概念,處于鎖定狀態(tài)時,RLock被某個線程擁有。擁有RLock的線程可以再次調(diào)用acquire(),釋放鎖時需要調(diào)用release()相同次數(shù)。
# import threading # import time # # v = [] # lock = threading.RLock() # def func (arg): # lock.acquire() # lock.acquire() # v.append(arg) # time.sleep(2) # m = v[-1] # print(arg,m) # lock.release() # lock.release() # for i in range(10): # t=threading.Thread(target=func, args=(i,)) # t.start()
3、BoundedSemaphore(1次放N個)信號量 Semaphore管理一個內(nèi)置的計(jì)數(shù)器,每當(dāng)調(diào)用acquire()時內(nèi)置計(jì)數(shù)器-1;調(diào)用release() 時內(nèi)置計(jì)數(shù)器+1;計(jì)數(shù)器不能小于0;當(dāng)計(jì)數(shù)器為0時,acquire()將阻塞線程直到其他線程調(diào)用release()。
# import time # import threading # # lock = threading.BoundedSemaphore(6) # def func(arg): # lock.acquire() # print(arg) # time.sleep(1) # lock.release() # # # for i in range(20): # t =threading.Thread(target=func,args=(i,)) # t.start()
4、Condition(1次方法x個) 通常與一個鎖關(guān)聯(lián)。需要在多個Contidion中共享一個鎖時,可以傳遞一個Lock/RLock實(shí)例給構(gòu)造方法,否則它將自己生成一個RLock實(shí)例。 import time import threading
lock = threading.Condition()
# ############## 方式一 ##############
def func(arg): print('線程進(jìn)來了') lock.acquire() lock.wait() # 加鎖
print(arg) time.sleep(1)
lock.release()
for i in range(10): t =threading.Thread(target=func,args=(i,)) t.start()
while True: inp = int(input('>>>'))
lock.acquire() lock.notify(inp) lock.release()
# ############## 方式二 ############## """ def xxxx(): print('來執(zhí)行函數(shù)了') input(">>>") # ct = threading.current_thread() # 獲取當(dāng)前線程 # ct.getName() return True
def func(arg): print('線程進(jìn)來了') lock.wait_for(xxxx) print(arg) time.sleep(1)
for i in range(10): t =threading.Thread(target=func,args=(i,)) t.start()
"""
5、Event 是最簡單的線程通信機(jī)制之一:一個線程通知事件,其他線程等待事件。(如同紅燈停,綠燈行)
# import time # import threading # # lock = threading.Event() # # # def func(arg): # print('線程來了') # lock.wait() # 加鎖:紅燈 # print(arg) # # # for i in range(10): # t =threading.Thread(target=func,args=(i,)) # t.start() # # input(">>>>") # lock.set() # 綠燈 # # # lock.clear() # 再次變紅燈 # # for i in range(10): # t =threading.Thread(target=func,args=(i,)) # t.start() # # input(">>>>") # lock.set()
二、 線程安全 線程安全:列表和字典線程安全 # import threading # # v = [] # def func(arg): # v.append(arg) # 線程安全 # print(v) # for i in range(10): # t =threading.Thread(target=func,args=(i,)) # t.start()
三、threadinglocal
可以把local看成是一個“線程-屬性字典”的字典,local封裝了從自身使用線程作為 key檢索對應(yīng)的屬性字典、再使用屬性名作為key檢索屬性值的細(xì)節(jié) threading.local作用:內(nèi)部自動為每一個線程維護(hù)一個空間{字典},用于當(dāng)前線程存取屬于自己的值,保證線程之間數(shù)據(jù)隔離。 # import time # import threading # # DATA_DICT = {} # # def func(arg): # ident = threading.get_ident() # DATA_DICT[ident] = arg # time.sleep(1) # print(DATA_DICT[ident],arg) # # # for i in range(10): # t =threading.Thread(target=func,args=(i,)) # t.start()
四、多線程池
# from concurrent.futures import ThreadPoolExecutor # import time # # def task(a1,a2): # time.sleep(2) # print(a1,a2) # # # 創(chuàng)建了一個線程池(最多5個線程) # pool = ThreadPoolExecutor(5) # # for i in range(40): # # 去線程池中申請一個線程,讓線程執(zhí)行task函數(shù)。 # pool.submit(task,i,8)
五、生產(chǎn)者消費(fèi)者模型 三部件: 生產(chǎn)者 隊(duì)列,先進(jìn)先出 擴(kuò)展: 棧,后進(jìn)先出 消費(fèi)者
思考:生產(chǎn)者消費(fèi)者模型解決了什么問題?不用一直等待的問題。 # # import time # import queue # import threading # q = queue.Queue() # 線程安全 # # def producer(id): # """ # 生產(chǎn)者 # :return: # """ # while True: # time.sleep(2) # q.put('包子') # print('廚師%s 生產(chǎn)了一個包子' %id ) # # for i in range(1,4): # t = threading.Thread(target=producer,args=(i,)) # t.start() # # # def consumer(id): # """ # 消費(fèi)者 # :return: # """ # while True: # time.sleep(1) # v1 = q.get() # print('顧客 %s 吃了一個包子' % id) # # for i in range(1,3): # t = threading.Thread(target=consumer,args=(i,)) # t.start()
|