进程的并行和并发
并行:两者同时执行。在微观上。两者在精确时间片刻同时进行
并发:资源有限的情况下,两者交替轮流使用资源。在宏观上,一段时间内两者同时进行
同步异常与阻塞非阻塞
同步和异步关注的是消息通信机制
同步:一个任务的完成需要依赖另一个任务时,只有等待被依赖的任务完成后,依赖的任务才算完成,这是一种可靠的任务序列,两个任务的状态保持一致
异步:不需要等待被依赖的任务完成,只是通知被依赖的任务要完成什么工作,依赖的任务也立即执行,只要自己完成了整个任务就算完成了。依赖它的任务无法确定被以来的任务是否完成,所以它是不可靠的任务序列
阻塞和非阻塞关注的是程序在等待调用结果(消息,返回值)时的状态
阻塞:阻塞调用是指调用结果返回之前,当前线程会被挂起。函数只有在得到结果之后才会返回
非阻塞:非阻塞和阻塞的概念相对应,指在不能立刻得到结果之前,该函数不会阻塞当前线程,而会立刻返回
同步与阻塞的区别:对于同步调用来说,很多时候当前线程还是激活的,只是从逻辑上当前函数没有返回而已。当socket工作在阻塞模式的时候, 如果没有数据的情况下调用该函数,则当前线程就会被挂起,直到有数据为止。简单的说就是同步时进程还在内存等待函数返回值,阻塞时线程被阻塞挂起到外存等待,直到函数返回值。
阻塞挂起状态:进程在外存并等待某事件的出现。
如何开启进程
Process类
from multiprocessing import Process
def write():
with open('abc','a')as f:
f.write('ly is sb')
f.write('\n')
if __name__ = '__main__': # windows中想开启进程,必须放在main里面
p = Process(target=write) # 1.实例化得到进程对象赋给对象p
# process传入参数target
# target -> 你要执行的任务(可以理解成函数)
# 意思是通知操作系统开启进程
p.start() # 2.必须调用start方法
Process参数
target=None, name=None, args=(), kwargs={}
target -> 你要执行的任务 # 意思是通知操作系统开启进程
name -> 进程名 # 输出当前的进程名,可对其进行操作
args -> 传给target指向的任务 # 传的是位置参数
kwargs -> 传给target指向的任务 # 传的是关键字参数
Process类的方法
p.start() # 开启进程必须使用的,运行主进程中途不等待子进程
p.run() # 调用run方法不会启动子进程
p.join() # 等待子进程执行完毕,再执行主进程
p.terminate() # 杀死进程用
p.is_alive() # 判断进程是否活着,返回布尔值,如果执行太快会返回之前的布尔值
Process类的属性
p.name # 进程名
p.pid # 进程id号
p.ppid # 父进程id号
p.daemon = True # 设置守护进程,主进程结束,子进程也结束,强调:必须放在start之前
获取进程id号
from multiprocessing import Process
import os
def write():
print('子进程的id号:%s'%os.getpid())
print('父进程的id号:%s'%os.getppid())
if __name__ == '__main__':
p = Process(target=write)
p.start()
print(p.pid)
print("main_主进程的id号:%s"%os.getpid())
print('main_父进程的id号:%s'%os.getppid())
同时运行多个进程
from multiprocessing import Process
import time
def write(i):
time.sleep(1)
print('这是第%s个进程'%i)
if __name__ == '__main__':
ll = []
for i in range(5):
p = Process(target=write,args=(i,))
p.start()
# p.join()
# 如果加join,需要等到上一个进程执行完再执行下一个进程,串行执行,这是不对的
ll.append(p)
for i in ll:
i.join()
高并发下的tcp服务端
import socket
from multiprocessing import Process
def tast(sock):
while True:
try:
data = sock.recv(1024)
print(data)
if len(data) == 0 :
break
sock.send(data.upper())
except Exception as e:
print(e)
break
sock.close()
if __name__ == '__main__':
server = socket.socket()
server.bind(('127.0.0.1', 8080))
server.listen(1)
while True:
sock, addr = server.accept()
print(sock)
print(addr)
p = Process(target=tast,args=(sock,))
p.start()
server.close()
# 只需要将之前的服务端拿来稍加修改即可,注意一定要在main下运行
进程锁
锁是保证一个进程执行结束后再进行下一个进程
from multiprocessing import Process,Lock
import os,time
def task(i, lock):
lock.acquire()
# 第一步:上锁,acquire函数
print('第%s个进程,进程id:%s执行开始了' % (i, os.getpid()))
time.sleep(1)
print('第%s个进程,进程id:%s执行结束了' % (i, os.getpid()))
lock.release()
# 第二步:释放锁,release函数
if __name__ == '__main__':
lock = Lock()
# 实例化得到一把锁,五个进程共用这把锁
for i in range(5):
p = Process(target=task, args=(i, lock))
p.start()