鎖與線程

-------------------------------------------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 '''
View Code

  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--------------------------------------------

相關文章
相關標籤/搜索