python中并发编程基础1
并发编程基础概念
1.进程。
什么是进程?
正在运行的程序就是进程。程序只是代码。
什么是多道?
多道技术:
1.空间上的复用(内存)。将内存分为几个部分,每个部分放入一个程序,这样同一时间在内存中就有了多道程序。
2.时间上的复用(CPU的分配)。只有一个CPU,如果程序在运行过程中遇到了I/O阻塞或者运行时间足够长。操作系统会按照算法将CPU分配给其他程序使用,依次类推。直到第一个程序被重新分配到CPU会继续运行。
多道技术中的问题解决:
空间复用:程序之间的内存必须分割。这种分割需要在硬件层面实现,由操作系统控制。保证安全性和稳定性。
multiprocessing模块的使用
python中的多线程无法利用多核优势,如果想要充分地使用多核CPU的资源,python中大部分情况需要使用多进程。python提供了multiprocessing模块。
multiprocessing模块是用来开启子进程,并可以在子进程中定制任务。
Process类
process类的作用是用来创建进程的类。
Process([group [, target [, name [, args [, kwargs]]]]]),由该类实例化得到的对象,表示一个子进程中的任务(尚未启动)
强调:需要使用关键字的方式来指定参数
args指定的为传给target函数的位置参数,是一个元组形式,必须有逗号
参数介绍:
1、group参数未使用,值始终为None
2、target表示调用对象,即子进程要执行的任务
3、args表示调用对象的位置参数元组,args=(1,2,'ming',)
4、kwargs表示调用对象的字典,kwargs={'name':'ming','age':20}
5、name为子进程的名称
- **方法介绍**:
1、p.start():启动进程,并调用该子进程中的p.run()
2、p.run():进程启动时运行的方法,正是它去调用target指定的函数,我们自定义类的类中一定要实现该方法
3、p.terminate():强制终止进程p,不会进行任何清理操作,如果p创建了子进程,该子进程就成了僵尸进程,使用该方法需要特别小心这种情况。如果p还保存了一个锁那么也将不会被释放,进而导致死锁
4、p.is_alive():如果p仍然运行,返回True
5、p.join([timeout]):主线程等待p终止(强调:是主线程处于等的状态,而p是处于运行的状态)。timeout是可选的超时时间,需要强调的是,p.join只能join住start开启的进程,而不能join住run开启的进程
- **属性介绍:**
1、p.daemon:默认值为False,如果设为True,代表p为后台运行的守护进程,当p的父进程终止时,p也随之终止,并且设定为True后,p不能创建自己的新进程,必须在p.start()之前设置
2、p.name:进程的名称
3、p.pid:进程的pid
4、p.exitcode:进程在运行时为None、如果为–N,表示被信号N结束(了解即可)
5、p.authkey:进程的身份验证键,默认是由os.urandom()随机生成的32字符的字符串。这个键的用途是为涉及网络连接的底层进程间通信提供安全性,这类连接只有在具有相同的身份验证键时才能成功(了解即可)
5.Process类的使用
- #创建进程的第一种方式
- ##注意:在windows 中,开启一个子进程就是完全复制一个父进程的代码并运行。如果不写在if __name__ == '__main__':下面会形成一个无穷的循环。if __name__ == '__main__':的作用是以当前文件运行__name__ 会== '__main__'
- from multiprocessing import Process
- import os
- def task():
- print('task run')
- print('子进程task', os.getpid())
- print('子进程task父进程', os.getppid())
- if __name__ == '__main__':
- #创建子进程p = Process
- p = Process(target=task, name= '这是子进程')
- p.start() # 给操作系统发送通知 要求操作系统开启进程,会自动调用run()方法
- print('py文件进程', os.getpid())
- print('py文件进程的父进程', os.getppid())
- ###输出结果
- py文件进程 10532
- py文件进程的父进程 15348
- task run
- 子进程task 4356
- 子进程task父进程 10532
- #开启进程的第二种方式
- #创建一个类,该类继承Process类,覆盖Process中的run方法,其优势是 可以自定义 进程的属性和行为 来完成一些额外任务 例如下载
- from multiprocessing import Process
- import os
- class MyProcess(Process):
- def __init__(self, url):
- self.url = url
- super().__init__()
- def run(self): #方法名必须是run
- print('下载文件。。。。', self.url)
- print('子进程run的进程ID', os.getpid())
- print('子进程run的父进程ID', os.getppid())
- if __name__ == '__main__':
- p = MyProcess('')
- p.start() #会自动执行run
- print('py文件的进程ID', os.getpid())
- print('py文件的父进程ID', os.getppid())
进程之间的内存空间是隔离的
- from multiprocessing import Process
- import time
-
- a = 1002020212
-
- def test():
- global a
- a = 33520
- print('test进程的a', a)
-
- if __name__ == '__main__':
- p = Process(target=test) #创建进程
- p.start() #启动进程
-
- time.sleep(1)
- print('py文件进程中的a', a)
- ###输出结果
- test进程的a 33520
- py文件进程中的a 1002020212
- 结论:
- 1.子进程中的数据修改,不会影响父进程。
- 2.子进程的创建和父进程无关。
- from multiprocessing import Process
Process对象的join方法
join方法的作用是:父进程等待子进程结束。
- from multiprocessing import Process
- import time
-
- def task(num):
- # time.sleep(2)
- print('我是%s号进程' % num)
-
- if __name__ == '__main__':
- start_time = time.time()
- ps = []
- for i in range(5):
- s = Process(target=task, args=(i,))
- s.start()
- ps.append(s)
- for n in ps:
- n.join(0.04)
- print(time.time()-start_time)
- print('over')
- from multiprocessing import Process
Process对象常用属性
- from multiprocessing import Process
- import time
-
- def test():
- time.sleep(3)
- print('life is so short, i use python')
-
- if __name__ == '__main__':
- p = Process(target=test, name='daidai')
- p.start()
- print(p.name) #进程名
- print(p.is_alive()) #进程是否存活
- # p.terminate() #终止进程
- print(p.pid)
- ###
- daidai
- True
- 20108
- life is so short, i use python
- from multiprocessing import Process
孤儿进程和僵尸进程
孤儿进程:是指父进程已经终止,但是自己还在运行
孤儿进程是无害的:例如QQ打开了浏览器, 然后QQ关闭,浏览器运行
僵尸进程:是指子进程完全执行完所有的任务,已经终止了但是还残留一些信息。(进程id 和 进程名等)
但是父进程没有处理这些残留信息,导致残留信息占用系统内存。
当出现大量的僵尸进程时,会占用系统资源,可以将他的父进程杀掉,僵尸成了孤儿,然后操作系统会负责收回内存。
- 基于多进程的TCP套接字通信
- ##基于多进程实现并发通信服务器
- from socket import *
- from multiprocessing import Process
- import struct
- server = socket()
- server.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
- server.bind(('127.0.0.1', 33520))
- server.listen()
- def communicate(c, addr):
- try:
- while True:
- data = c.recv(4) #
- msg_len = struct.unpack('i', data)[0]
- msg_data = c.recv(msg_len) #
- if not msg_data:
- err_info = '对方正在输入!'
- err_info_data = err_info.encode('utf-8')
- back_len_data = struct.pack('i', len(err_info_data))
- c.send(back_len_data)
- c.send(err_info_data)
- back_len = struct.pack('i', len(msg_data))
- c.send(back_len)
- c.send(msg_data)
- print(msg_data.decode('utf-8'))
- except Exception as e:
- print(e)
- if __name__ == '__main__':
- while True:
- c, addr = server.accept()
- p = Process(target=communicate, name=None, args=(c, addr))
- p.start()
- #客户端,可开启多个,但是每连接一个就开启一个进程
- from socket import *
- import struct
- client = socket()
- client.connect(('127.0.0.1', 33520))
- while True:
- msg = input('请输入发送的消息:').strip()
- msg_data = msg.encode('utf-8')
- msg_len_s = struct.pack('i', len(msg_data))
- client.send(msg_len_s)
- client.send(msg_data)
- data_len = client.recv(4) #收到消息长度
- length = struct.unpack('i', data_len)[0]
- data = client.recv(length)
- back_msg = data.decode('utf-8')
- print('返回的消息:%s' % back_msg)
python中并发编程基础1的更多相关文章
- python中网络编程基础
一:什么是c\s架构 1.c\s即client\server 客户端\服务端架构. 客户端因特定的请求而联系服务器并发送必要的数据等待服务器的回应最后完成请求 服务端:存在的意义就是等待客户端的请求, ...
- TCP与UDP比较 以及并发编程基础知识
一.tcp比udp真正可靠地原因 1.为什么tcp比udp传输可靠地原因: 我们知道在传输数据的时候,数据是先存在操作系统的缓存中,然后发送给客户端,在客户端也是要经过客户端的操作系统的,因为这个过程 ...
- Java并发编程基础
Java并发编程基础 1. 并发 1.1. 什么是并发? 并发是一种能并行运行多个程序或并行运行一个程序中多个部分的能力.如果程序中一个耗时的任务能以异步或并行的方式运行,那么整个程序的吞吐量和可交互 ...
- Python 3 并发编程多进程之进程同步(锁)
Python 3 并发编程多进程之进程同步(锁) 进程之间数据不共享,但是共享同一套文件系统,所以访问同一个文件,或同一个打印终端,是没有问题的,竞争带来的结果就是错乱,如何控制,就是加锁处理. 1. ...
- Python 3 并发编程多进程之队列(推荐使用)
Python 3 并发编程多进程之队列(推荐使用) 进程彼此之间互相隔离,要实现进程间通信(IPC),multiprocessing模块支持两种形式:队列和管道,这两种方式都是使用消息传递的. 可以往 ...
- 并发-Java并发编程基础
Java并发编程基础 并发 在计算机科学中,并发是指将一个程序,算法划分为若干个逻辑组成部分,这些部分可以以任何顺序进行执行,但与最终顺序执行的结果一致.并发可以在多核操作系统上显著的提高程序运行速度 ...
- Java并发编程系列-(1) 并发编程基础
1.并发编程基础 1.1 基本概念 CPU核心与线程数关系 Java中通过多线程的手段来实现并发,对于单处理器机器上来讲,宏观上的多线程并行执行是通过CPU的调度来实现的,微观上CPU在某个时刻只会运 ...
- Java并发编程基础三板斧之Semaphore
引言 最近可以进行个税申报了,还没有申报的同学可以赶紧去试试哦.不过我反正是从上午到下午一直都没有成功的进行申报,一进行申报 就返回"当前访问人数过多,请稍后再试".为什么有些人就 ...
- Java高并发编程基础三大利器之CountDownLatch
引言 上一篇文章我们介绍了AQS的信号量Semaphore<Java高并发编程基础三大利器之Semaphore>,接下来应该轮到CountDownLatch了. 什么是CountDownL ...
随机推荐
- python自学第13天 hashlib,re模块
import hashlib sha=hashlib.sha3_512()#定义加密成什么格式 sha.update('how to use sha1 in 年后 '.encode('utf-8')) ...
- TCP/IP笔记(1)
TCP/IP 背景和介绍 上世纪 70 年代,随着计算机技术的发展,计算机使用者意识到:要想发挥计算机更大的作用,就要将世界各地的计算机连接起来.但是简单的连接是远远不够的,因为计算机之间无法沟通.因 ...
- Beta版——爱阅APP功能说明书
爱阅APP功能说明书 一.引言 通过Alpha发布和一些用户的反馈信息,了解到我们APP存在的问题.针对这些问题我们做了一些修改.以下内容是Beta版的功能说明书. 二.工具 安卓手机 爱阅APP安装 ...
- Python全栈之路----函数----返回值
函数外部的代码想要获取函数的执行结果,就可以在函数里用return语句,把结果返回. def stu_register(name,age,course='PY',country='CN'): prin ...
- Floodlight1.2+Mininet的安装及使用
直接转载的大神的,亲测Ubuntu16.04版本没问题 https://www.sdnlab.com/19189.html
- jquery常用指令
table中td多行展示: ```css td { word-wrap: break-word; } ``` div模态框: <div id="loading" style= ...
- matplotlib.pyplot展示MNIST图片
import torch import torch.utils.data as Data import torchvision import torchvision.transforms as tra ...
- 数学:确定性的丧失 (M·克莱因 著)
第一章 数学真理的起源 (已看) 第二章 数学真理的繁荣 (已看) 第三章 科学的数学化 (已看) 第四章 第一场灾难:真理的丧失 (已看) 第五章 一门逻辑科学不合逻辑的发展 (已看) 第六章 分析 ...
- ipc基础
ipc对象持久性 进程持久性:具有这种持久性的对象在持有它的最后一个进程关闭了该对象为止 内核持久性:这种IPC对象一直存在直到内核重新自举或显示删除该对象为止 文件系统持久性:具有这种持久性的对象只 ...
- ubuntu安装驱动问题
网友答案:https://blog.csdn.net/jasonzhoujx/article/details/80469139