并发编程

---恢复内容开始---

首先要了解的知识点:
1、什么是程序?什么是进程?
程序说白了就是一堆文件
进程就是一个正在执行的过程/程序

所以说进程是一个抽象的概念
这个概念起源操作系统

2、什么是操作系统
定义:
操作系统是位于计算机硬件与应用软件之间
用于协调、管理、控制计算机硬件与软件的资源的
一种控制程序

3、操作系统的两大作用:
1、把复杂丑陋的硬件操作都封装成美丽的接口,提供给应用程序使用
2、把进程对硬件的竞争变的有序

4、串行:把几个程序从硬盘读到内存,然后cpu从内存一条条读取程序,一条条执行程序,本质上也是一个个完成程序


5、多道技术
多道的产生背景是想要在单个cpu的情况下实现多个进程并发执行的效果


1、空间上的复用 (多道程序复用内存的空间,程序与程序在内存的空间是相互隔离的,是物理上的隔离)
2、时间上的复用 (多道程序复用CPU时间,实现并发)
当cpu遇到IO操作要切换(提升效率)
一个进程占用cpu时间过长也切(降低效率)

进程与进程之间的内存空间是互相隔离的
并行与并发:
并行是同一时间执行多道程序,这只存在与多个cpu的情况下,单个cpu只能实现并发。无论是并发还是并行,在用户看来都是'同时’运行的,因为cpu的
运算时间极快所以我们肉眼根本无法发现是不是同时运行。
并发:单核+多道技术就可以实现并发,是伪并行
并行:只有具有多个cpu才能实现
基于UDP协议实现并发:
udp不需要经过3次握手和4次挥手,不需要建立链接,直接发数据就可以了。

TCP与udp的区别:tcp需要建立链接,发送数据必须要收到对方确认收到才能继续发送数据,而且不能单方面断链接,优点是可靠,数据不易丢失
udp不需要建链接,客户端只需要发数据,不需要确认服务端是否收到,也可以单方面断链接,优点是发送效率高,缺点是容易丢失数据

#服务端
import
socket server=socket.socket(socket.AF_INET,socket.SOCK_DGRAM) # 数据报协议 server.bind(('127.0.0.1',8080)) while True: client_data,client_addr=server.recvfrom(1024) msg=input('回复%s:%s>>>:' %(client_addr[0],client_addr[1])) server.sendto(msg.encode('utf-8'),client_addr)
#客户端1
import
socket client=socket.socket(socket.AF_INET,socket.SOCK_DGRAM) # 数据报协议 while True: msg=input('>>>: ').strip() client.sendto(msg.encode('utf-8'),('127.0.0.1',8080)) res,server_addr=client.recvfrom(1024) print(res.decode('utf-8'))
客户端2
import
socket client=socket.socket(socket.AF_INET,socket.SOCK_DGRAM) # 数据报协议 while True: msg=input('>>>: ').strip() client.sendto(msg.encode('utf-8'),('127.0.0.1',8080)) res,server_addr=client.recvfrom(1024) print(res.decode('utf-8'))

进程:

进程的创建:process模块

Process([group [, target [, name [, args [, kwargs]]]]]),由该类实例化得到的对象,表示一个子进程中的任务(尚未启动)

强调:
1. 需要使用关键字的方式来指定参数
2. args指定的为传给target函数的位置参数,是一个元组形式,必须有逗号

group参数未使用,值始终为None

target表示调用对象,即子进程要执行的任务

args表示调用对象的位置参数元组,args=(1,2,'egon',)

kwargs表示调用对象的字典,kwargs={'name':'egon','age':18}

name为子进程的名称

 

 方法介绍:

p.start():启动进程,并调用该子进程中的p.run() 
p.run():进程启动时运行的方法,正是它去调用target指定的函数,我们自定义类的类中一定要实现该方法  

p.terminate():强制终止进程p,不会进行任何清理操作,如果p创建了子进程,该子进程就成了僵尸进程,使用该方法需要特别小心这种情况。如果p还保存了一个锁那么也将不会被释放,进而导致死锁
p.is_alive():如果p仍然运行,返回True

p.join([timeout]):主线程等待p终止(强调:是主线程处于等的状态,而p是处于运行的状态)。timeout是可选的超时时间,需要强调的是,p.join只能join住start开启的进程,而不能join住run开启的进程

 

属性介绍:

p.daemon:默认值为False,如果设为True,代表p为后台运行的守护进程,当p的父进程终止时,p也随之终止,并且设定为True后,p不能创建自己的新进程,必须在p.start()之前设置

p.name:进程的名称

p.pid:进程的pid

p.exitcode:进程在运行时为None、如果为–N,表示被信号N结束(了解即可)

p.authkey:进程的身份验证键,默认是由os.urandom()随机生成的32字符的字符串。这个键的用途是为涉及网络连接的底层进程间通信提供安全性,这类连接只有在具有相同的身份验证键时才能成功(了解即可)

 

      开启子进程的两种方式:

#第一种:直接定义方法,用函数的形式(一般用这种方法)
from
multiprocessing import Process import time def task(name): print('%s is running' %name) time.sleep(3) print('%s is done' %name) if __name__ == '__main__': # 在windows系统之上,开启子进程的操作一定要放到这下面 # Process(target=task,kwargs={'name':'egon'}) p=Process(target=task,args=('egon',)) p.start() # 向操作系统发送请求,操作系统会申请内存空间,然后把父进程的数据拷贝给子进程,作为子进程的初始状态 print('======主') #第二种:用类方法 from multiprocessing import Process import time class MyProcess(Process): def __init__(self,name): super(MyProcess,self).__init__() self.name=name def run(self): print('%s is running' %self.name) time.sleep(3) print('%s is done' %self.name) if __name__ == '__main__': p=MyProcess('egon') p.start() print('')

 进程间的空间是隔离的:

from multiprocessing import Process
n=100 #在windows系统中应该把全局变量定义在if __name__ == '__main__'之上就可以了
def work():
    global n
    n=0
    print('子进程内: ',n)


if __name__ == '__main__':
    p=Process(target=work)
    p.start()          #隔离方法
    print('主进程内: ',n)



join方法:回收子进程的资源

from multiprocessing import Process
import time
import random

class Piao(Process):
def __init__(self,name):
self.name=name
super().__init__()
def run(self):
print('%s is piaoing' %self.name)
time.sleep(random.randrange(1,3))
print('%s is piao end' %self.name)


p=Piao('egon')
p.start()
p.join(0.0001) #等待p停止,等0.0001秒就不再等了
print('开始')

join:主进程等,等待子进程结束

 

posted @ 2018-04-24 18:23  鲁之敬  阅读(64)  评论(0编辑  收藏  举报