day32 并发编程之锁
生活随笔
收集整理的這篇文章主要介紹了
day32 并发编程之锁
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
并發(fā)編程之鎖
1. GIL全局解釋器鎖
2. GIL與普通的互斥鎖
3. 死鎖
4. 信號量
5. event事件
6. 線程q
?
1. GIL全局解釋器鎖
?
?
""" In CPython, the global interpreter lock, or GIL, is a mutex that prevents multiple native threads from executing Python bytecodes at once. This lock is necessary mainly because CPython’s memory management is not thread-safe. """ """ ps:python解釋器有很多種 最常見的就是Cpython解釋器 GIL本質(zhì)也是一把互斥鎖:將并發(fā)變成串行犧牲效率保證數(shù)據(jù)的安全 用來阻止同一個進程下的多個線程的同時執(zhí)行(同一個進程內(nèi)多個線程無法實現(xiàn)并行但是可以實現(xiàn)并發(fā))python的多線程沒法利用多核優(yōu)勢 是不是就是沒有用了?GIL的存在是因為CPython解釋器的內(nèi)存管理不是線程安全的垃圾回收機制1.引用計數(shù)2.標(biāo)記清除3.分代回收研究python的多線程是否有用需要分情況討論 四個任務(wù) 計算密集型的 10s 單核情況下開線程更省資源 多核情況下開進程 10s開線程 40s四個任務(wù) IO密集型的 單核情況下開線程更節(jié)省資源 多核情況下開線程更節(jié)省資源 """""" python的多線程到底有沒有用 需要看情況而定 并且肯定是有用的多進程+多線程配合使用 """計算密集型
# 計算密集型 from multiprocessing import Process from threading import Thread import os, timedef work():res = 0for i in range(10000000):res *= iif __name__ == '__main__':l = []print(os.cpu_count()) # 本機為8核start = time.time()for i in range(8):p = Process(target=work) # 耗時 0.7752041816711426# p = Thread(target=work) # 耗時 2.9953091144561768 l.append(p)p.start()for p in l:p.join()stop = time.time()print('run time is %s' % (stop - start))?
I/O密集型 # IO密集型 from multiprocessing import Process from threading import Thread import threading import os,time def work():time.sleep(2)if __name__ == '__main__':l=[]print(os.cpu_count()) #本機為8核start=time.time()for i in range(4000): # 報錯超過最大遞歸深度,這里改為400p=Process(target=work) #耗時2.85s多,大部分時間耗費在創(chuàng)建進程上# p=Thread(target=work) #耗時2.02s多 l.append(p)p.start()for p in l:p.join()stop=time.time()print('run time is %s' %(stop-start))?
?
2. GIL與普通的互斥鎖
from threading import Thread import timen = 100def task():global ntmp = ntime.sleep(1) # 睡1秒,所有子進程都取到了100,阻塞1秒后再減1,結(jié)果為99# 注銷了time.sleep(1),GIL鎖發(fā)揮作用,串行取值,100-100個子程序的1=0n = tmp - 1t_list = [] for i in range(100):t = Thread(target=task)t.start()t_list.append(t)for t in t_list:t.join()print(n) # 0?
?
3.死鎖
from threading import Thread,Lock,current_thread,RLock import time """ Rlock可以被第一個搶到鎖的人連續(xù)的acquire和release 每acquire一次鎖身上的計數(shù)加1 每release一次鎖身上的計數(shù)減1 只要鎖的計數(shù)不為0 其他人都不能搶""" # mutexA = Lock() # mutexB = Lock() mutexA = mutexB = RLock() # A B現(xiàn)在是同一把鎖class MyThread(Thread):def run(self): # 創(chuàng)建線程自動觸發(fā)run方法 run方法內(nèi)調(diào)用func1 func2相當(dāng)于也是自動觸發(fā) self.func1()self.func2()def func1(self):mutexA.acquire()print('%s搶到了A鎖'%self.name) # self.name等價于current_thread().name mutexB.acquire()print('%s搶到了B鎖'%self.name)mutexB.release()print('%s釋放了B鎖'%self.name)mutexA.release()print('%s釋放了A鎖'%self.name)def func2(self):mutexB.acquire()print('%s搶到了B鎖'%self.name)time.sleep(1)mutexA.acquire()print('%s搶到了A鎖' % self.name)mutexA.release()print('%s釋放了A鎖' % self.name)mutexB.release()print('%s釋放了B鎖' % self.name)for i in range(10):t = MyThread()t.start()class Demo(object): passobj1 = Demo()obj2 = Demo()print(id(obj1),id(obj2)) """ 只要類加括號實例化對象 無論傳入的參數(shù)是否一樣生成的對象肯定不一樣 單例模式除外自己千萬不要輕易的處理鎖的問題 """?
4 信號量
# 信號量可能在不同的領(lǐng)域中 對應(yīng)不同的知識點 """ 互斥鎖:一個廁所(一個坑位) 信號量:公共廁所(多個坑位) """ from threading import Semaphore,Thread import time import randomsm = Semaphore(5) # 造了一個含有五個的坑位的公共廁所def task(name):sm.acquire()print('%s占了一個坑位'%name)time.sleep(random.randint(1,3))sm.release()for i in range(40):t = Thread(target=task,args=(i,))t.start()?
?
5 Event事件
from threading import Event,Thread import time# 先生成一個event對象 e = Event()def light():print('紅燈正亮著')time.sleep(3)e.set() # 發(fā)信號print('綠燈亮了')def car(name):print('%s正在等紅燈'%name)e.wait() # 等待信號print('%s加油門飆車了'%name)t = Thread(target=light) t.start()for i in range(10):t = Thread(target=car,args=('傘兵%s'%i,))t.start()?
?
6 線程q
import queue """ 同一個進程下的多個線程本來就是數(shù)據(jù)共享 為什么還要用隊列因為隊列是管道+鎖 使用隊列你就不需要自己手動操作鎖的問題 因為鎖操作的不好極容易產(chǎn)生死鎖現(xiàn)象 """# q = queue.Queue() # q.put('hahha') # print(q.get())# q = queue.LifoQueue() # q.put(1) # q.put(2) # q.put(3) # print(q.get())# q = queue.PriorityQueue() # # 數(shù)字越小 優(yōu)先級越高 # q.put((10,'haha')) # q.put((100,'hehehe')) # q.put((0,'xxxx')) # q.put((-10,'yyyy')) # print(q.get())?
?
轉(zhuǎn)載于:https://www.cnblogs.com/Ryan-Yuan/p/11351820.html
總結(jié)
以上是生活随笔為你收集整理的day32 并发编程之锁的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 论文学习21-Globally Norm
- 下一篇: 国科大高级人工智能-总结