目录
1 创建进程的两种方式
第一种
from multiprocessing import Process
import time
def task(n):
print('我是子进程')
time.sleep(n)
print('子进程结束')
if __name__ == '__main__':
# args=(), kwargs={}
# t=Process(task,args=(1,))
t = Process(target=task, kwargs={'n': 1})
t.start() # 通知操作系统,开启进程,执行task函数
print('主')
第二种:
from multiprocessing import Process
import time
class Task(Process):
def __init__(self, n):
super().__init__()
self.n = n
def run(self):
print('我是子进程')
time.sleep(self.n)
print('子进程结束')
if __name__ == '__main__':
t = Task(1)
# t.run(1) # 不是调用t.run(),而是调用t.start()
t.start()
print('主')
join的使用
from multiprocessing import Process
import time
def task(n):
print('我是子进程')
time.sleep(n)
print('子进程结束')
if __name__ == '__main__':
ctime = time.time()
t = Process(target=task, kwargs={'n': 1})
t2 = Process(target=task, kwargs={'n': 2})
t.start()
t2.start()
t.join() # 等待t子进程执行完成
t2.join() # 等待t2子进程执行完成
print('主')
ctime2 = time.time()
print(ctime2 - ctime)
进程之间数据隔离
from multiprocessing import Process
import time
age = 18
def task(n):
global age # 局部修改全局
age = 99
print('我是子进程')
time.sleep(n)
print('子进程结束')
print(age)
if __name__ == '__main__':
t = Process(target=task, kwargs={'n': 1})
t.start()
t.join() # 等待t子进程执行完成
print('主')
print(age) # 数据没有变,主进程中打印age和子进程的age没有半毛钱关系,数据是隔离的
2.进程的其他方法
from multiprocessing import Process,current_process
import time
import os
# 每个进程都会有自己的id号pid
def task():
print('子进程')
# 当前进程的id号
print(current_process().pid)
print(os.getpid()) # 跟上面打印出来是一模一样的
# 取出该进程父id号
print('-----',os.getppid())
# current_process()当前进程对象
print(current_process().is_alive())
time.sleep(2)
print('子进程结束')
if __name__ == '__main__':
t = Process(target=task, )
t.start()
# t1 = Process(target=task, )
# t1.start()
# t.is_alive() # t这个进程是否存活
# print('主进程打印的结果',t.is_alive())
print(t.pid)
time.sleep(0.5)
# t.terminate() # 把t进程关闭
# time.sleep(0.1)
print('主进程打印的结果', t.is_alive())
守护进程
from multiprocessing import Process, current_process
import time
import os
def task():
# print(os.getpid())
print('子进程')
time.sleep(200)
print('子进程结束')
if __name__ == '__main__':
t = Process(target=task, )
# 守护进程:主进程一旦结束,子进程也结束
# t.daemon=True # 一定要加在启动之前
t.start()
time.sleep(1)
print('主进程结束')
print(os.getppid())
time.sleep(100)
# 问题1 :主进程的父进程是谁?就是pycharm
# 问题2 :主进程开了很多子进程,每个都需要设置守护吗?看你的需求,你想让某个进程是守护:t.daemon=True
3.互斥锁
from multiprocessing import Process, Lock
import json
import time
import random
def search():
# 查票的函数
# 打开文件,读出ticket_count
with open('ticket', 'r', encoding='utf-8') as f:
dic = json.load(f)
print('余票还有:', dic.get('ticket_count'))
def buy():
with open('ticket', 'r', encoding='utf-8') as f:
dic = json.load(f)
time.sleep(random.randint(1, 3)) # 模拟一下网络延迟
if dic.get('ticket_count') > 0:
# 能够买票
dic['ticket_count'] -= 1
# 保存到文件中去
with open('ticket', 'w', encoding='utf-8') as f:
json.dump(dic, f)
print('买票成功')
else:
# 买票失败
print('买票失败')
写一个函数,先查票,再买票
def task(mutex):
search()
# 买票过程要加锁
# 买前加锁
# mutex.acquire()
# buy() # 10个进程变成了串行执行
# # 买后释放锁
# mutex.release()
with mutex:
buy()
if __name__ == '__main__':
# 锁的创建,在哪?主进程创建锁
mutex = Lock() # 创建一把锁
# 模拟十个人买票(开10个进程)
for i in range(10):
t = Process(target=task, args=(mutex,))
t.start()
面向对象高级:魔法方法(__开头的),enter__和__exit,上下文管理器
自己写一个类,实现类似于打开文件 with open 的功能
with MyClass(‘文件名’,‘方式’,‘编码’) as f:
f.read()
在这写代码,f就关闭了
class MyClass():
def __init__(self,file_name,mode,encoding):
self.file_name=file_name
self.mode=mode
self.encoding=encoding
def __enter__(self):
print('只要有with,就会执行我')
self.file=open(self.file_name,self.mode,encoding=self.encoding)
return self.file
def __exit__(self, exc_type, exc_val, exc_tb):
# 只要顶格写代码,就会执行我
print('只要顶格写代码,就会执行我')
self.file.close()
with MyClass('ticket','r','utf-8') as f:
print(f.read())
print('xxss')
print("sdfadasf")
# a=MyClass('ticket','r','utf-8')
4.队列
from multiprocessing import Queue
# 实例化得到要给对象
q=Queue(5) # 默认很大,可以放很多,写了个5,只能放5个
# 往管道中放值
q.put(1)
q.put('lqz')
q.put(18)
q.put(19)
# q.put(20)
# q.put(21)
# q.put_nowait(100)
# 从管道中取值
# print(q.get())
# print(q.get())
# print(q.get())
# print(q.get(timeout=100)) # 等0.1s还没有值,就结束
# print(q.get_nowait()) # 不等了,有就是有,没有就没有
print(q.empty()) # 看一下队列是不是空的
print(q.full()) # 看一下队列是不是满的
# 总结:
'''
q=Queue(队列大小)
# 放值
q.put(asdf)
q.put_nowait(asdf) # 队列满了,放不进去就不放了,报错
# 取值
q.get() # 从队列头部取出一个值
q.get_nowait() # 从队列头部取值,没有就抛错
# 队列是否为空,是否满
print(q.empty()) # 看一下队列是不是空的
print(q.full()) # 看一下队列是不是满的
'''
5.进程间通信
from multiprocessing import Process, current_process, Queue
import time
import os
def task1(q):
print('我是task1进程,我的id号是:%s'%os.getpid())
q.put('lqz is handsome')
def task2(q):
# res=q.get()
# print('我是task2进程,我的id号是:%s'%os.getpid(),res)
print('我是task2进程,我的id号是:%s'%os.getpid())
if __name__ == '__main__':
q = Queue(5)
t1 = Process(target=task1, args=(q,))
t1.start()
t2 = Process(target=task2, args=(q,))
t2.start()
print(q.get())
1 并发编程总体课程
操作系统发展史(了解)
多道技术(了解)
进程调度(讲)
进程三状态(就绪,阻塞,运行)
同步异步 阻塞非阻塞:异步+非阻塞
创建进程的两种方式(重点)
join方法
进程间数据相互隔离
僵尸进程与孤儿进程
进程对象及其他方法
守护进程
互斥锁
队列介绍
IPC机制
生产者消费者模型
线程理论
开启线程的两种方式
TCP服务端实现并发效果
线程对象join方法
同一个进程下的多个线程
线程对象及其他方法
线程互斥锁
GIL全局解释器锁理论
GIP与普通互斥锁的区别
多线程与多进程比较
死锁现象
递归锁
信号量
Event事件
线程q
池的概念
线程池
进程池
协程基本原理
gevent模块
协程实现tcp并发
io模型介绍
阻塞io模型
非阻塞io模型理论
非阻塞io模型代码演示
io多路复用
asyncio模块
io模型
2 内容回顾
2.1 操作系统发展史
https://www.cnblogs.com/xiaoyuanqujing/articles/11715635.html
2.2 多道技术(了解)
https://www.cnblogs.com/xiaoyuanqujing/articles/11715646.html
2.4 同步异步 阻塞非阻塞
-flask,django3.0以前,都是同步框架
-tornado,sanic,fastAPI 异步框架
2.5 创建进程的两种方式(重点)
### 1 创建进程的两种方式
# 第一种
# from multiprocessing import Process
# import time
#
#
# def task(n):
# print('我是子进程')
# time.sleep(n)
# print('子进程结束')
#
#
# if __name__ == '__main__':
# # args=(), kwargs={}
# # t=Process(task,args=(1,))
# t = Process(target=task, kwargs={'n': 1})
# t.start() # 通知操作系统,开启进程,执行task函数
# print('主')
# 第二种:
# from multiprocessing import Process
# import time
#
# class Task(Process):
# def __init__(self, n):
# super().__init__()
# self.n = n
#
# def run(self):
# print('我是子进程')
# time.sleep(self.n)
# print('子进程结束')
#
#
# if __name__ == '__main__':
# t = Task(1)
# # t.run(1) # 不是调用t.run(),而是调用t.start()
# t.start()
# print('主')
2.6 join方法
# join的使用:等待子进程执行完成
# from multiprocessing import Process
# import time
#
#
# def task(n):
# print('我是子进程')
# time.sleep(n)
# print('子进程结束')
#
#
# if __name__ == '__main__':
# ctime = time.time()
# t = Process(target=task, kwargs={'n': 1})
# t2 = Process(target=task, kwargs={'n': 2})
# t.start()
# t2.start()
# t.join() # 等待t子进程执行完成
# t2.join() # 等待t2子进程执行完成
# print('主')
# ctime2 = time.time()
# print(ctime2 - ctime)
2.7 进程间数据相互隔离
# 进程之间数据隔离
from multiprocessing import Process
import time
age = 18
def task(n):
global age # 局部修改全局
age = 99
print('我是子进程')
time.sleep(n)
print('子进程结束')
print(age)
if __name__ == '__main__':
t = Process(target=task, kwargs={'n': 1})
t.start()
t.join() # 等待t子进程执行完成
print('主')
print(age) # 数据没有变,主进程中打印age和子进程的age没有半毛钱关系,数据是隔离的
3 今日内容
3.1 进程调度
# 1 先来先服务
# 2 短作业优先
# 3 时间片轮转
# 4 多级反馈队列
易语言
3.2 僵尸进程与孤儿进程
#1 僵尸进程:进程结束了,资源还没来得及回收
#2 孤儿进程:主进程挂了,子进程还没结束,它就会被专门的进程接管
3.3 进程对象及其他方法
# 1 windows:tasklist |findstr 进程id号
# 2 mac,Linux:ps aux | grep 进程id号
# 3 进程对象:t=Process(target=task, )或者是在进程内部:current_process()
# 4 t.pid或者current_process().pid 获取进程id号
# 5 os.getpid() 同上,获取进程id号
# 6 os.getppid() 获取父进程id号,子进程中获取父进程id,等于父进程的id号
# 7 t.is_alive()或者current_process().is_alive() 查看进程是否存活
# 8 t.terminate() 关闭进程,在主进程关闭
3.4 守护进程
from multiprocessing import Process,current_process
import time
import os
def task():
print(os.getpid())
print('子进程')
time.sleep(200)
print('子进程结束')
if __name__ == '__main__':
t = Process(target=task, )
# 守护进程:主进程一旦结束,子进程也结束
# t.daemon=True # 一定要加在启动之前
t.start()
time.sleep(1)
print('主进程结束')
3.5 互斥锁
# 同时只有一个人能拿到,必须释放,其他人才能再次获取到
from multiprocessing import Process, Lock
import json
import time
import random
def search():
# 查票的函数
# 打开文件,读出ticket_count
with open('ticket', 'r', encoding='utf-8') as f:
dic = json.load(f)
print('余票还有:', dic.get('ticket_count'))
def buy():
with open('ticket', 'r', encoding='utf-8') as f:
dic = json.load(f)
time.sleep(random.randint(1, 3)) # 模拟一下网络延迟
if dic.get('ticket_count') > 0:
# 能够买票
dic['ticket_count'] -= 1
# 保存到文件中去
with open('ticket', 'w', encoding='utf-8') as f:
json.dump(dic, f)
print('买票成功')
else:
# 买票失败
print('买票失败')
# 写一个函数,先查票,再买票
def task(mutex):
search()
# 买票过程要加锁
# 买前加锁
# mutex.acquire()
# buy() # 10个进程变成了串行执行
# # 买后释放锁
# mutex.release()
with mutex:
buy()
if __name__ == '__main__':
# 锁的创建,在哪?主进程创建锁
mutex = Lock() # 创建一把锁
# 模拟十个人买票(开10个进程)
for i in range(10):
t = Process(target=task, args=(mutex,))
t.start()
3.6 队列介绍
from multiprocessing import Queue
# 实例化得到要给对象
q=Queue(5) # 默认很大,可以放很多,写了个5,只能放5个
# 往管道中放值
q.put(1)
q.put('lqz')
q.put(18)
q.put(19)
# q.put(20)
# q.put(21)
# q.put_nowait(100)
# 从管道中取值
# print(q.get())
# print(q.get())
# print(q.get())
# print(q.get(timeout=100)) # 等0.1s还没有值,就结束
# print(q.get_nowait()) # 不等了,有就是有,没有就没有
print(q.empty()) # 看一下队列是不是空的
print(q.full()) # 看一下队列是不是满的
# 总结:
'''
q=Queue(队列大小)
# 放值
q.put(asdf)
q.put_nowait(asdf) # 队列满了,放不进去就不放了,报错
# 取值
q.get() # 从队列头部取出一个值
q.get_nowait() # 从队列头部取值,没有就抛错
# 队列是否为空,是否满
print(q.empty()) # 看一下队列是不是空的
print(q.full()) # 看一下队列是不是满的
'''
3.7 IPC机制(进程间通信)
# Inter-Process Communication,进程间通信
from multiprocessing import Process, current_process, Queue
import time
import os
def task1(q):
print('我是task1进程,我的id号是:%s'%os.getpid())
q.put('lqz is handsome')
def task2(q):
# res=q.get()
# print('我是task2进程,我的id号是:%s'%os.getpid(),res)
print('我是task2进程,我的id号是:%s'%os.getpid())
if __name__ == '__main__':
q = Queue(5)
t1 = Process(target=task1, args=(q,))
t1.start()
t2 = Process(target=task2, args=(q,))
t2.start()
print(q.get())