一、进程之间通信

进程的任务有三种状态:运行,就绪,阻塞。

加锁可以让多个进程修改同一块数据时,同一时间只能由一个任务可以进行修改,即串行的修改。牺牲了速度,保证了数据安全。

虽然可以使用文件共享数据实现进程间的通信,但是效率太低,还需要自己加锁处理。为了解决这些问题,便使用到了multiprocessing模块为我们提供的基于消息的IPC通信机制:队列和管道

1.队列和管道都是将数据存放于内存中

2.队列是基于管道+锁的机制实现的。

我们应该尽量避免使用共享数据,多使用队列。

队列:

创建队列的类:

Queue([maxsize]):创建共享的进程队列,Queue是多进程安全的队列,可以使用Queue实现多进程之间的数据传递。 

maxsize是队列中允许的最大项数,省略则无大小限制

q = Queue()
q.put() 括号里可以是任意类型,不能是大数据

主要方法:

1 q.put方法用以插入数据到队列中,put方法还有两个可选参数:blocked和timeout。如果blocked为True(默认值),并且timeout为正值,该方法会阻塞timeout指定的时间,直到该队列有剩余的空间。如果超时,会抛出Queue.Full异常。如果blocked为False,但该Queue已满,会立即抛出Queue.Full异常。没有参数时,q.put的个数大于队列数时,会一直阻塞住。
2 q.get方法可以从队列读取并且删除一个元素。同样,get方法有两个可选参数:blocked和timeout。如果blocked为True(默认值),并且timeout为正值,那么在等待时间内没有取到任何元素,会抛出Queue.Empty异常。如果blocked为False,有两种情况存在,如果Queue有一个值可用,则立即返回该值,否则,如果队列为空,则立即抛出Queue.Empty异常。没有参数时,q.get的个数大于队列数时,会一直阻塞住。3.q.put_nowait()等价于q.put(block=False)队列满时再存也会抛异常q.get_nowait()等价于q.get(block=False)队列为空取不出时会抛异常

from multiprocessing import Queueq=Queue(3)  #1.不应该放大数据  2.可以任意类型
q.put(['first',])
q.put({'x':2,})
q.put(3)
# q.put(6)#阻塞在存放的时候,当有内容被取出时才推出阻塞模式print(q.get())
print(q.get())
print(q.get())
# print(q.get())#阻塞在取的时候,当有新内容添加进去才退出阻塞状态

test

生产者消费者模型:

在并发编程中使用生产者和消费者模式能够解决绝大多数并发问题。该模式通过平衡生产线程和消费线程的工作能力来提高程序的整体处理数据的速度。通俗的讲就是当程序中出现明显的两类任务,一类负责生产数据,一类负责处理数据,就可以引入这个模型来实现生产者与消费者的解耦合,平衡生产力与消费能力,从而提升效率。

初级版本:

import time
import random
from multiprocessing import Process,Queuedef producer(name,food,q):for i in range(4):res = '%s%s'%(food,i)time.sleep(random.randint(1,3))q.put(res)print('厨师[%s]生产了%s'%(name,res))def consumer(name,q):while True:res = q.get()# if res ==None:breaktime.sleep(random.randint(1,3))print('吃货%s吃了%s'%(name,res))if __name__ == '__main__':q = Queue()#生产者p1 = Process(target=producer,args=('egon','包子',q))p2 = Process(target=producer,args=('lxx','豆浆',q))p3 = Process(target=producer,args=('cw','油条',q))#消费者c1 = Process(target=consumer,args=('alex',q))c2 = Process(target=consumer,args=('yxf',q))p1.start()p2.start()p3.start()c1.start()c2.start()print('主')

test1

这个时候就有一个问题,主进程一直在阻塞状态,永远不会结束。这是因为消费者在取空以后 还一直在原地阻塞着。

解决方法:让生产者在生产完毕后再往队列中发送一个结束信号,这样消费者在收到结束信号后跳出循环

版本二:

import time
import random
from multiprocessing import Process,Queuedef producer(name,food,q):for i in range(4):res = '%s%s'%(food,i)time.sleep(random.randint(1,3))q.put(res)print('厨师[%s]生产了%s'%(name,res))def consumer(name,q):while True:res = q.get()if res ==None:breaktime.sleep(random.randint(1,3))print('吃货%s吃了%s'%(name,res))if __name__ == '__main__':q = Queue()#生产者p1 = Process(target=producer,args=('egon','包子',q))p2 = Process(target=producer,args=('lxx','豆浆',q))p3 = Process(target=producer,args=('cw','油条',q))#消费者c1 = Process(target=consumer,args=('alex',q))c2 = Process(target=consumer,args=('yxf',q))p1.start()p2.start()p3.start()c1.start()c2.start()p1.join()p2.join()p3.join()q.put(None)q.put(None)q.put(None)print('主')

test2

但是有几个生产者我们就要发送几个None,这不够优雅,于是我们导入了JoinableQueue模块

#JoinableQueue([maxsize]):这就像是一个Queue对象,但队列允许项目的使用者通知生成者项目已经被成功处理。通知进程是使用共享的信号和条件变量来实现的。#参数介绍:
    maxsize是队列中允许最大项数,省略则无大小限制。    #方法介绍:
    JoinableQueue的实例p除了与Queue对象相同的方法之外还具有:q.task_done():使用者使用此方法发出信号,表示q.get()的返回项目已经被处理。如果调用此方法的次数大于从队列中删除项目的数量,将引发ValueError异常q.join():生产者调用此方法进行阻塞,直到队列中所有的项目均被处理。阻塞将持续到队列中的每个项目均调用q.task_done()方法为止

版本三:

import time
import random
from multiprocessing import Process,JoinableQueuedef producer(name,food,q):for i in range(4):res = '%s%s'%(food,i)time.sleep(random.randint(1,3))q.put(res)print('厨师[%s]生产了%s'%(name,res))def consumer(name,q):while True:res = q.get()time.sleep(random.randint(1,3))print('吃货%s吃了%s'%(name,res))q.task_done()if __name__ == '__main__':q = JoinableQueue()#生产者p1 = Process(target=producer,args=('egon','包子',q))p2 = Process(target=producer,args=('lxx','豆浆',q))p3 = Process(target=producer,args=('cw','油条',q))#消费者c1 = Process(target=consumer,args=('alex',q))c2 = Process(target=consumer,args=('yxf',q))c1.daemon=Truec2.daemon=Truep1.start()p2.start()p3.start()c1.start()c2.start()p1.join()p2.join()p3.join()q.join()#主进程等q结束,即q内数据被取干净了。print('主')

View Code

二、线程理论

进程是资源单位,由若干线程组成的,一个进程至少有一个线程,线程是操作系统直接支持的执行单元。一个进程相当于一块空间,空间内有若干的线程,就好比进程是一个车间,线程就是车间的流水线。同一个进程之间的线程是资源共享的。进程是程序执行的过程,那么线程就是程序执行的代码。

线程相比进程的优点:1.同一进程下,多个线程共享进程内的资源

          2.创建线程的开销远远小于进程

三、线程的使用

(一).创建线程的两种方式(和进程类似)

from threading import Thread
import timedef task(name):print('%s is running'%name)time.sleep(2)print('%s is done'%name)if __name__ == '__main__':t = Thread(target=task,args=('进程一',))t.start()print('主')

方式一

直接导入threading模块

from threading import Thread
import timeclass Mythead(Thread):def __init__(self,name):super().__init__()self.name = namedef run(self):print('%s is running' % self.name)time.sleep(0.1)print('%s is done' % self.name)if __name__ == '__main__':t = Mythead('线程一')t.start()print('主')

方式二

继承Therad类重写run方法

(二).线程特性介绍

os模块下的getpid()线程也适用
current_thread#查看当前线程
active_count#查看线程的活跃个数(线程已结束的不是活跃状态)
current_thread().name查看线程名字
略

(三).守护线程

无论是进程还是线程都遵循  某线程/进程等待 主线程/进程  运行完毕后才会被销毁。强调:运行完毕并非终止运行

#1.对主进程来说,运行完毕指的是主进程代码运行完毕。
    主进程在其代码结束后就已经算运行完毕了(守护进程在此时就被回收),然后主进程会一直等非守护的子进程都运行完毕后回收子进程的资源(否则会产生僵尸进程),才会结束,#2.对主线程来说,运行完毕指的是主线程所在的进程内所有非守护线程统统运行完毕,主线程才算运行完毕。主线程在其他非守护线程运行完毕后才算运行完毕(守护线程在此时就被回收)。因为主线程的结束意味着进程的结束,进程整体的资源都将被回收,而进程必须保证非守护线程都运行完毕后才能结束。

from threading import Thread
from multiprocessing import Process
import time
def foo():print(123)time.sleep(1)print("end123")def bar():print(456)time.sleep(3)print("end456")if __name__ == '__main__':t1=Thread(target=foo)t2=Thread(target=bar)# t1=Process(target=foo)# t2=Process(target=bar)t1.daemon=Truet1.start()t2.start()print("main-------")

进程与线程的区别

(四).线程的互斥锁

不加锁的情况

from threading import Thread,Lock
import timemutex=Lock()
n=100
def task():global n# mutex.acquire()temp=ntime.sleep(0.1)n=temp-1# mutex.release()if __name__ == '__main__':t_l=[]for i in range(100):t=Thread(target=task)t_l.append(t)t.start()for t in t_l:t.join()print(n)

View Code

结果永远为99,因为线程速度太快了,并发的时候都读到了n=100,所以需要给他加上锁

加上锁的情况

from threading import Thread,Lock
import timemutex=Lock()
n=100
def task():global nmutex.acquire()temp=ntime.sleep(0.1)n=temp-1mutex.release()if __name__ == '__main__':t_l=[]for i in range(100):t=Thread(target=task)t_l.append(t)t.start()for t in t_l:t.join()print(n)

View Code

焚膏油以继晷,恒兀兀以穷年。

python-进程之间通信、多线程介绍相关推荐

  1. python—多进程之进程之间通信

    一.Queue 1.导入:from multiprocessing import Queue 2.进程间数据通信之Queue示意图: mq.put(i) 子进程1发送数据到队列Queue中,子进程2和 ...

  2. Python 进程之间共享数据(全局变量)

    Python 进程之间共享数据(全局变量) 进程之间共享数据(数值型): import multiprocessing def func(num): num.value=10.78 #子进程改变数值的 ...

  3. Windows使用自定义消息实现进程之间通信

    Windows使用自定义消息实现进程之间通信         Windows程序与其它类型程序的区别就是使用消息,例如键盘或鼠标消息等,在dos系统下的程序没有定义消息.在windows操作系统中,消 ...

  4. python进程socket通信_python实现多进程通信实例分析

    操作系统会为每一个创建的进程分配一个独立的地址空间,不同进程的地址空间是完全隔离的,因此如果不加其他的措施,他们完全感觉不到彼此的存在.那么进程之间怎么进行通信?他们之间的关联是怎样的?实现原理是什么 ...

  5. 使用命名管道进程之间通信(转)

    原文地址:http://www.cnblogs.com/yukaizhao/archive/2011/08/04/system-io-pipes.html 命名管道: 命名管道的功能比匿名管道更强大, ...

  6. 什么是进程?Python进程各部分内容介绍

    程序是一个没有生命的实体,它包含许多由程序设计语言编写的.但未被执行的指令,这些指令经过编译和执行才能完成指定动作. 程序被执行后成为了一个活动的实体,这个实体就是进程.换言之,操作系统调度并执行程序 ...

  7. 为什么无名管道只能用于具有亲缘关系的进程之间通信

    作业: 个人理解: 因为亲缘关系的进程之间共享文件描述符,而无名管道文件也是一个文件,可以通过文件描述符进行通信. 而非亲缘关系的进程之间不共享文件描述符,所以不能使用无名管道进行通信.

  8. python进程socket通信_Python Socket TCP双端聊天功能实现过程详解

    SOCKET编程 socket(套接字):是一个网络通信的端点,能实现不同主机的进程通信, -通过IP+端口定位对方并发送消息的通信机制 分为UDP和TCP 客户端Client: 发起访问的一-方 服 ...

  9. python进程socket通信_python3 进程间通信之socket.socketpair()

    python3 进程间通信之socket.socketpair() socket.socketpair()是什么鬼东西? socket.socketpair()函数仅返回两个已经连接的套接字对象,参数 ...

  10. python进程socket通信_python之socket初识

    本篇文章主要讲的是 socket基本操作.包括 网络通信三要素.TCP三次握手以及socket通信流程等.希望感兴趣的小伙伴可以坚持看下去同时欢迎提出宝贵的意见让我们一起进步! 01:OSI模型 1) ...

最新文章

  1. Scala与Java交互
  2. uploadify初体验
  3. C++操作SQLite简明教程
  4. SAP CRM 查询单据的时候 BAdI 里面的排序字段为何有些不生效
  5. easy datagrid 按钮控制
  6. Kiterunner上下文感知型内容搜索工具
  7. 《Orange'S:一个操作系统的实现》与上一版之比较
  8. APP社交类源代码分享直接上车
  9. 如何批量把照片设置统一尺寸?
  10. educoder算法设计与分析 实验三 动态规划实验
  11. 华为的薪酬体系整体框架,值得收藏
  12. VGA分辨率无法识别或错误通过添加自定义配置参数正确显示(Ubuntu/Windows)
  13. java 读usb口 用POS-58 90U 打印
  14. php使用cookie获取浏览记录,php使用cookie存库浏览记录详解
  15. html5获取视频帧,从HTML5和JavaScript的视频捕获帧
  16. 密集脚集成块的手工焊接方法
  17. Keil uVision5 创建STM32F4
  18. 【问】批量删除作废会员的语句
  19. 【软考软件评测师】2020年下综合知识历年真题
  20. Minio 在Linux环境部署报错error occured ErrorResponse(code=InternalError, message=We encountered an internal

热门文章

  1. 南京大学计算机学院推免名单,南大计算机系招收2014级研究生外校推免生复试名单...
  2. 计算机英语boot,英语单词boot怎么读,boot的音标是什么,boot是什么意思 - 音标网
  3. 暴走漫画 Rage Comic
  4. 《泽诺尼亚5》游戏评
  5. C# 20. 弹出对话框
  6. 如何关掉 PC QQ 烦人的 QQ 频道
  7. 关键字finalize
  8. 浦东时报特供:浦东公共文化融入智慧城市建设
  9. 2023年最新最全软件测试面试题大全
  10. 安搭Share:世界上最北端的小米专卖店开设 位于北极圈内