进程通讯和线程通讯

进程通讯和线程通讯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

  上面的代码是会一直运行的,这里是手动中止的结果!

相关文章
相关标签/搜索