-------------------------------------------START-------------------------------------------併發
1.同步鎖(Lock):socket
鎖一般被用來實現共享資源的同步訪問.爲買一個共享資源建立一個Lock對象,當你須要訪問該資源時,調用acquire方法來獲取鎖對象(若是其餘線程已經得到了該鎖,則當前線程需等待其被釋放),待資源訪問完後,再調用release方法釋放鎖.
ide
1 import threading 2 3 R=threading.Lock() 4 5 R.acquire() 6 ''' 7 對公共數據的操做 8 ''' 9 R.release()
2.死鎖與遞歸鎖:函數
所謂死鎖:是指兩個或兩個以上的進程或線程在執行過程當中,因爭奪資源而形成的一種互相等待的現象,若無外力做用,它們都將沒法推動下去.此時稱系統處於死鎖狀態或系統產生了死鎖,這些永遠在互相等待的進程稱爲死鎖進程.
ui
在Python中爲了支持在同一線程中屢次請求同一資源,Python提供了可重入鎖RLock.這個RLock內部維護着一個Lock和一個counter變量,counter記錄了acquire的次數,從而使得資源能夠被屢次require.直到一個線程全部的acquire都被release,其餘線程才能得到資源.
spa
3.Event對象:操作系統
在初始狀況下,Event對象中的信號標誌被設置爲假.若是有線程等待一個Event對象,而這個Event對象的標誌爲假,那麼這個線程將會被一直阻塞直至該標誌爲真.
線程
1 event.isSet():返回event的狀態值; 2 3 event.wait():若是 event.isSet()==False將阻塞線程; 4 5 event.set(): 設置event的狀態值爲True,全部阻塞池的線程激活進入就緒狀態, 等待操做系統調度; 6 7 event.clear():恢復event的狀態值爲False。
1 import threading 2 import time 3 import logging 4 5 logging.basicConfig(level=logging.DEBUG, format='(%(threadName)-10s) %(message)s',) 6 7 def worker(event): 8 logging.debug('okkkkkkkkkkkkkk------') 9 while not event.isSet(): #默認 FALSE 10 logging.debug('loading..............') 11 event.wait() 12 logging.debug(' coollllllllllllllllllllllllll[%s]', time.ctime()) 13 time.sleep(3) 14 15 def main(): 16 readis_ready = threading.Event() 17 t1 = threading.Thread(target=worker, args=(readis_ready,), name='t1') 18 t1.start() 19 20 t2 = threading.Thread(target=worker, args=(readis_ready,), name='t2') 21 t2.start() 22 23 logging.debug('-------------Me-is-a-fengexian---------') 24 time.sleep(6) # simulate the check progress 25 readis_ready.set() #將event狀態設置爲TRUE 26 27 if __name__=="__main__": 28 main()
4.Semaphore(信號量):debug
Semaphore管理一個內置的計數器,
code
每當調用acquire()時內置計數器-1;
調用release()時內置計數器+1;
計數器不能小於0;當計數器爲0時,acquire()將阻塞線程直到其餘線程調用release().
1 import threading,time 2 3 semaphore=threading.Semaphore(100) 4 def fun(): 5 if semaphore.acquire(): 6 print(threading.current_thread().getName(),'get semaphore') 7 time.sleep(2) 8 semaphore.release() 9 for i in range(1000): 10 t1=threading.Thread(target=fun) 11 t1.start()
5.協程:
1.yield與協程:
1 import time 2 3 """ 4 傳統的生產者-消費者模型是一個線程寫消息,一個線程取消息,經過鎖機制控制隊列和等待,但一不當心就可能死鎖。 5 若是改用協程,生產者生產消息後,直接經過yield跳轉到消費者開始執行,待消費者執行完畢後,切換回生產者繼續生產,效率極高。 6 """ 7 # 注意到consumer函數是一個generator(生成器): 8 # 任何包含yield關鍵字的函數都會自動成爲生成器(generator)對象 9 10 def consumer(): 11 r = '' 12 while True: 13 # 三、consumer經過yield拿到消息,處理,又經過yield把結果傳回; 14 # yield指令具備return關鍵字的做用。而後函數的堆棧會自動凍結(freeze)在這一行。 15 # 當函數調用者的下一次利用next()或generator.send()或for-in來再次調用該函數時, 16 # 就會從yield代碼的下一行開始,繼續執行,再返回下一次迭代結果。經過這種方式,迭代器能夠實現無限序列和惰性求值。 17 n = yield r 18 if not n: 19 return 20 print('[CONSUMER] ←← Consuming %s...' % n) 21 time.sleep(1) 22 r = '200 OK' 23 def produce(c): 24 # 一、首先調用c.next()啓動生成器 25 next(c) 26 n = 0 27 while n < 5: 28 n = n + 1 29 print('[PRODUCER] →→ Producing %s...' % n) 30 # 二、而後,一旦生產了東西,經過c.send(n)切換到consumer執行; 31 cr = c.send(n) 32 # 四、produce拿到consumer處理的結果,繼續生產下一條消息; 33 print('[PRODUCER] Consumer return: %s' % cr) 34 # 五、produce決定不生產了,經過c.close()關閉consumer,整個過程結束。 35 c.close() 36 if __name__=='__main__': 37 # 六、整個流程無鎖,由一個線程執行,produce和consumer協做完成任務,因此稱爲「協程」,而非線程的搶佔式多任務。 38 c = consumer() 39 produce(c) 40 41 42 ''' 43 result: 44 45 [PRODUCER] →→ Producing 1... 46 [CONSUMER] ←← Consuming 1... 47 [PRODUCER] Consumer return: 200 OK 48 [PRODUCER] →→ Producing 2... 49 [CONSUMER] ←← Consuming 2... 50 [PRODUCER] Consumer return: 200 OK 51 [PRODUCER] →→ Producing 3... 52 [CONSUMER] ←← Consuming 3... 53 [PRODUCER] Consumer return: 200 OK 54 [PRODUCER] →→ Producing 4... 55 [CONSUMER] ←← Consuming 4... 56 [PRODUCER] Consumer return: 200 OK 57 [PRODUCER] →→ Producing 5... 58 [CONSUMER] ←← Consuming 5... 59 [PRODUCER] Consumer return: 200 OK 60 '''
2.greenlet
greenlet機制主要思想:生成器函數或者協程函數中的yield語句掛起函數的執行,直到少受使用next()或send()操做進行恢復爲止,可使用一個調度器循環在一組生成器函數之間協做多個任務,greentle是Python中實現咱們所謂的"Coroutine(協程)"的一個基礎庫.
1 from greenlet import greenlet 2 3 def test1(): 4 print (12) 5 gr2.switch() 6 print (34) 7 gr2.switch() 8 9 def test2(): 10 print (56) 11 gr1.switch() 12 print (78) 13 14 gr1 = greenlet(test1) 15 gr2 = greenlet(test2) 16 gr1.switch()
greenlet提供了一個在libev事件循環頂部的高級別併發API.
gevent特色:
<1> 基於libev的快速事件循環,Linux上面的是epoll機制
<2> 基於greenlet的輕量級執行單元
<3> API複用了Python標準庫裏的內容
<4> 支持SSL的協做式sockets
<5> 可經過線程池或c-ares實現DNS查詢
<6> 經過monkey patching功能來使得第三方模塊變成協做式
PS:協程:
1.因爲單線程,不能再切換!
2.再也不有任何鎖的概念
-----------------------------------------2017-05-09------------------------------------------------------------------------------------END--------------------------------------------