進程通訊和線程通訊

進程通訊和線程通訊html

進程間通訊:python

  進程是擁有獨立空間的,若是開多個進程對某個數據進行處理,因爲進程是獨立空間,那麼兩個進程如何通訊擁有共同數據庫

空間呢?咱們能夠在父進程裏啓動一個服務器進程開闢一個公共空間。開啓以後在子進程處理數據,父進程也會出現相應的服務器

效果。Manager 是專門用來作共享的!dom

 1 from multiprocessing import Process, Manager  2 mgr = Manager()  3 d = mgr.dict()  4 def func(d):  5 d['a'] = 'a'  6 print(d)  7 p = Process(target=func, args=(d,))  8 p.start()  9 p.join() 10 print(d) 11 # 運行結果: 12 {'a': 'a'} 13 {'a': 'a'}

  使用Manager以後會失效資源共享,那麼出現資源競爭怎麼辦?(參照線程資源競爭)咱們可使用隊列,它默認使用了ide

鎖的功能!使用會很是方便。post

 1 from multiprocessing import Process, Queue  2 q = Queue()  3 q.put(1)  4  5  6 def func(q):  7 print(q.get())  8 q.put(2)  9 10 11 p = Process(target=func, args=(q,)) 12 p.start() 13 p.join() 14 print(q.get()) 15 # 返回結果:(代表隊列是共有資源,能夠共享) 16 1
17 2

  若是直接用  import queue  發現資源並無共享!ui

 

線程間通訊:spa

  線程間是共享空間的,每一個線程對數據的修改都會起做用。若是兩個線程同時修改,那麼若是線程一尚未修改完,線程線程

二就開始修改,這樣就會出問題,這個時候就須要線程鎖來解決,相似於數據庫裏的原子操做(最小的操做單元,必須執行完才

能執行其餘的)。

 1 from threading import Thread  2 a = 0  3 n = 10000000  4 def incr(n):  5 global a  6 for i in range(n):  7 a += 1  8 def dncr(n):  9 global a 10 for i in range(n): 11 a -= 1 12 t1 = Thread(target=incr, args=(n,)) 13 t2 = Thread(target=dncr, args=(n,)) 14 t1.start() 15 t2.start() 16 t1.join() 17 t2.join() 18 print(a) 19 # 運行屢次的結果: 20 -288397 -122765 -1761997

  能夠看出上面的代碼出現了資源競爭的狀況致使錯誤執行,咱們使用鎖來控制資源共享:

 1 from threading import Thread, Lock  2  3 a = 0  4 n = 10000000  5 lock = Lock() # 建立一把鎖  6  7 def incr(n):  8 global a  9 for i in range(n): 10 lock.acquire() # 獲取一把鎖 11 a += 1 12 lock.release() # 釋放鎖 13 14 15 def dncr(n): 16 global a 17 for i in range(n): 18 lock.acquire() # 獲取一把鎖 19 a -= 1 20 lock.release() # 釋放鎖 21 22 23 t1 = Thread(target=incr, args=(n,)) 24 t2 = Thread(target=dncr, args=(n,)) 25 t1.start() 26 t2.start() 27 t1.join() 28 t2.join() 29 print(a)

  建立鎖也可使用with lock:  部分代碼以下:運行結果都爲0:

1 def incr(n): 2 global a 3 for i in range(n): 4  with lock: 5 a += 1

 

消費者模式和生產者模式:

  生產者只關心隊列是否已經滿了,沒有就生產,往隊列裏添加

  消費者只關心隊列是否爲空,爲空就阻塞

 1 import threading  2 import random  3 import queue  4  5  6 class Producer(threading.Thread):  7  8 def __init__(self, queue):  9 super().__init__() 10 self.queue = queue 11 12 def run(self): 13 for i in range(10): 14 r = random.randint(0, 9) 15 if self.queue.qsize() < 3: 16  self.queue.put(r) 17 print('往隊列裏添加一個數據{}'.format(r)) 18 19 20 class Consumer(threading.Thread): 21 22 def __init__(self, queue): 23 super().__init__() 24 self.queue = queue 25 26 def run(self): 27 for i in range(10): 28 r = random.randint(0, 9) 29 if self.queue.empty(): 30 data = self.queue.get() 31 print('從隊列裏get一個數據{}'.format(data)) 32 33 34 if __name__ == '__main__': 35 q = queue.Queue() 36 p1 = Producer(q) 37 c1 = Consumer(q) 38  p1.start() 39  c1.start() 40  p1.join() 41  c1.join() 42 q.join()

  這裏代碼會阻塞,由於咱們沒法知道兩個線程誰先執行,是沒有規律的,線程p1幾乎是瞬間將循環執行完,因此線程p1

只put了3個數據進去。線程c1在get數據的時候也只能取3個了,而後隊列爲空,會進去阻塞狀態!能夠對代碼進行改進:

 1 import threading  2 import random  3 import queue  4 import time  5  6  7 class Producer(threading.Thread):  8  9 def __init__(self, queue): 10 super().__init__() 11 self.queue = queue 12 13 def run(self): 14 while True: 15 r = random.randint(0, 9) 16 if not self.queue.full(): 17  self.queue.put(r) 18 print('往隊列裏添加一個數據{}'.format(r)) 19 time.sleep(1) 20 else: 21 print('隊列滿了') 22 23 24 class Consumer(threading.Thread): 25 26 def __init__(self, queue): 27 super().__init__() 28 self.queue = queue 29 30 def run(self): 31 while True: 32 data = self.queue.get() 33 print('從隊列裏get一個數據{}'.format(data)) 34 time.sleep(1) 35 36 37 if __name__ == '__main__': 38 q = queue.Queue(5) 39 p1 = Producer(q) 40 c1 = Consumer(q) 41  p1.start() 42  c1.start() 43  p1.join() 44  c1.join() 45  q.join() 46 47 # 代碼運行結果: 48 往隊列裏添加一個數據4 49 從隊列裏get一個數據4 50 往隊列裏添加一個數據9 51 從隊列裏get一個數據9 52 ^CTraceback (most recent call last): 53 File "/home/pyvip/tz_spider/通訊/xianchengtongxin.py", line 73, in <module> 54  p1.join() 55 File "/usr/lib/python3.5/threading.py", line 1054, in join 56  self._wait_for_tstate_lock() 57 File "/usr/lib/python3.5/threading.py", line 1070, in _wait_for_tstate_lock 58 elif lock.acquire(block, timeout): 59 KeyboardInterrupt 60 往隊列裏添加一個數據3 61 從隊列裏get一個數據3 62 往隊列裏添加一個數據7 63 從隊列裏get一個數據7 64 往隊列裏添加一個數據9 65 從隊列裏get一個數據9 66 往隊列裏添加一個數據9 67 從隊列裏get一個數據9 68 往隊列裏添加一個數據4 69 從隊列裏get一個數據4 70 71 Process finished with exit code -1

  上面的代碼是會一直運行的,這裏是手動中止的結果!

相關文章
相關標籤/搜索