什么是进程
进程就是程序运行的过程,程序是死的,进程是动态的,是有一定的生命周期的,进程又包含线程,正真干活的是线程,一个程序启动两次就会启动两个就进程,这两个都是操作系统决定的,程序员可以决定的叫协程。
什么是并行和并发
并行是真正意义上的同时运行,在一个精确的时间片刻中,要求多核
并发是看起来像同时运行,其实是cpu在快速的来回切换
同步异步阻塞非阻塞
同步:
"""
一个任务的完成要依赖于另外一个任务。
比如说:你想打游戏,看到有朋友在线,然后发起一个预约,你要等到你这个朋友打完这把,你才开始打游戏
"""
异步:
"""
异步呢就是和同步相反,一个任务的完成不需要依赖于另外一个任务
比如: 就拿上面打游戏的例子,你朋友游戏刚刚开始,你跟你朋友讲,打完了叫你,你去干别的事了。
"""
阻塞,非阻塞:
"""
程序在等待调用结果(消息,返回值)时的状态
继续上面的例子:你在等待你朋友打完这把游戏的过程中,你啥都不做,直到你朋友打完,这个过程就是阻塞的,表现在程序中就是该程序阻塞在函数调用处不能继续往下执行。相反,你在等待过程中要么开了一把游戏,又或者你退出去刷刷抖音,聊聊天,这就是非阻塞。
"""
同步阻塞:
"""
效率最低
就拿上面的例子说,你预约了你朋友,然后你啥也不干,就在那等着你朋友打完。
"""
异步阻塞:
"""
异步就是处理消息,阻塞就是等待消息处理的结果
异步操作也是可以被阻塞住的,只不过不是在处理消息的时候阻塞,而是在等待消息的时候阻塞
如上例子:你点击了预约,你告诉你朋友打完了喊你,你其实也是被阻塞在了想打游戏这个操作上面。
"""
同步非阻塞:
"""
效率也是很低的
"""
异步非阻塞:
"""
效率是最高的
"""
开启进程
import time
from multiprocessing import Process
def f(name):
print('hello', name)
print('我是子进程')
if __name__ == '__main__': # win创建进程要在main函数里面
p = Process(target=f, args=('bob',))
p.start()
time.sleep(1)
print('执行主进程的内容了')
进程的方法
p.name # 打印进程名
p.run() # 进程启动时运行的方法,由它去调用target指定的函数,调用者方法,不会启动子进程,第二种开启进程的方法时会用到这个run(),不能与p.strat()连用
p.join() # 等待子进程运行完毕,在执行主进程
p.is_alive() # 判读进程是否存活,打印出来的时bool值
p.terminate() # 杀死进程,注意杀死进程不是立即马上杀死,这个杀死是需要一点时间的
获取进程id
from multiprocessing import Process
import os
def func(name):
print('子进程的id', os.getpid()) # 就是当前子进程的id
print('子进程的父进程id, 也就是开启这个子进程的父进程id',os.getppid()) # 子进程的父进程id
if __name__ == '__main__':
p = Process(target=func, args=('egon', ))
p.start()
print('开启的子进程的id',p.pid) # 这个同func的os.getpid()
print('主进程的id' ,os.getpid())# 这个同func的os.getppid()
print('主进程的父进程,这里就是pycharm的id' ,os.getppid())
循环创建多个进程
from multiprocessing import Process
def func(i):
print(f'开启的第{i}个进程')
if __name__ == '__main__':
for i in range(5):
p = Process(target=func, args=(i, ))
p.start()
多进程配合join方法
from multiprocessing import Process
def func(i):
print(f'开启的第{i}个进程')
if __name__ == '__main__':
ll = []
for i in range(5):
p = Process(target=func, args=(i, ))
p.start()
ll.append(p)
for j in ll:
j.join()
print('主进程is running')
'''
这里不能把join方法加入创建进程的循环里面,因为如果放在这个里面,并发就变成串行了
所以要把这个join放在另外一个循环里面
'''
实现一个高并发的socke服务端,基于tcp
from multiprocessing import Process
import socket
def task(conn):
while True:
try:
data = conn.recv(1024)
if len(data) == 0:
break
print(data)
conn.send(data.upper())
except Exception as e:
print(e)
break
conn.close()
if __name__ == '__main__':
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind(('127.0.0.1', 8080))
server.listen(5)
while True:
conn, addr = server.accept()
p = Process(target=task, args=(conn,))
p.start()
server.close()
进程锁
from multiprocessing import Process, Lock
import time
def func(i, lock):
lock.acquire() # 上锁
print(f'第{i}个进程is running')
time.sleep(1)
print(f'第{i}个进程is over')
lock.release() # 释放锁
if __name__ == '__main__':
ll = []
lock = Lock()
for i in range(5):
p = Process(target=func, args=(i, lock))
p.start()
ll.append(p)
for j in ll:
j.join()
"""
加锁之后就可以实现一个并发的那个函数一个进程执行完在执行另外一个
"""
用进程锁模拟实现一个12306抢票
"""
用锁模拟一个12306抢票的功能,用一个json文件存储一个字典,表示还有几张票
买票的时候加入锁
"""
import json
import random
import time
from multiprocessing import Process, Lock
def search(i):
"""
查票
:return:
"""
with open('a.json', 'r', encoding='utf-8')as f:
d1 = json.load(f)
print(f"用户{i}查询余票,当前余票还有{d1.get('count')}张")
def buy(i):
"""
买票
:return:
"""
with open('a.json', 'r', encoding='utf-8') as f:
ticket_dic = json.load(f)
if ticket_dic.get('count') > 0:
ticket_dic['count'] -= 1
with open('a.json', 'w', encoding='utf-8')as f:
json.dump(ticket_dic, f)
print(f'用户{i}抢票成功')
else:
print(f'用户{i}抢票失败')
def run(i, lock):
search(i)
time.sleep(random.randint(1,3))
lock.acquire()
buy(i)
time.sleep(random.randint(1, 3))
lock.release()
if __name__ == '__main__':
ll = []
lock = Lock()
for i in range(5):
p = Process(target=run, args=(i, lock))
p.start()
ll.append(p)
for p in ll:
p.join()