|
|
# 多任务介绍
|
|
|
什么是多任务?
|
|
|
操作系统可以同时执行多个任务
|
|
|
|
|
|
现在的操作系统:windows mac linux unix
|
|
|
这些操作系统 都支持多任务
|
|
|
|
|
|
单核CPU如何实现多任务?
|
|
|
表面看,每个任务都是同时执行,实际上是每个任务在轮询着执行,只是因为CPU的调度太快,导致我们感觉像是所有任务都在同时执行
|
|
|
|
|
|
多核CPU如何实现多任务?
|
|
|
是真正实现了多个任务同时执行
|
|
|
|
|
|
并发:看上去一起执行,任务数大于CPU核心数
|
|
|
并行:一起执行,任务数必须小于等于CPU核心数
|
|
|
|
|
|
实现多任务的方式:
|
|
|
1、多进程方式
|
|
|
2、多线程方式
|
|
|
3、协程方式
|
|
|
4、多进程+多线程
|
|
|
|
|
|
### 没有多进程
|
|
|
|
|
|
```python
|
|
|
import time
|
|
|
def func():
|
|
|
while True:
|
|
|
print("this is a process2")
|
|
|
time.sleep(1.5)
|
|
|
if __name__ == '__main__':
|
|
|
while True:
|
|
|
print("this is a process1")
|
|
|
time.sleep(1)
|
|
|
func()
|
|
|
|
|
|
```
|
|
|
|
|
|
### multiprocessing 多进程
|
|
|
|
|
|
```python
|
|
|
from multiprocessing import Process
|
|
|
import time,os
|
|
|
|
|
|
def func(str):
|
|
|
|
|
|
#os.getpid 获取当前进程的进程号
|
|
|
|
|
|
#os.getppid 获取当前进程的父进程
|
|
|
|
|
|
while True:
|
|
|
print("this is process 2--%s--%s--%s"%(str,os.getpid(),os.getppid()))
|
|
|
time.sleep(1.5)
|
|
|
|
|
|
if __name__ == '__main__':
|
|
|
print("父进程启动...--%s--%s"%(os.getpid(),os.getppid()))
|
|
|
# 创建子进程
|
|
|
# target 说明进程的任务
|
|
|
p = Process(target=func,args=("python",))
|
|
|
# 启动进程
|
|
|
p.start()
|
|
|
# 主进程中的
|
|
|
while True:
|
|
|
print("this is a process 1--%s--%s"%(os.getpid(),os.getppid()))
|
|
|
time.sleep(1)
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
### 让父进程等待子进程结束之后父进程再结束
|
|
|
|
|
|
```python
|
|
|
from multiprocessing import Process
|
|
|
from time import sleep
|
|
|
|
|
|
def func():
|
|
|
print("子进程启动...")
|
|
|
sleep(3)
|
|
|
print("子进程结束...")
|
|
|
|
|
|
if __name__ == '__main__':
|
|
|
print("父进程启动...")
|
|
|
p = Process(target = func)
|
|
|
p.start()
|
|
|
# sleep(1)
|
|
|
# 让父进程等待子进程结束之后父进程再结束
|
|
|
# timeout 超时时间 父进程的等待时间
|
|
|
p.join()
|
|
|
#执行后一直等待
|
|
|
print("父进程结束...")
|
|
|
```
|
|
|
|
|
|
### 在子进程中修改全局变量 对父进程中的全局变量没有影响
|
|
|
|
|
|
```python
|
|
|
from multiprocessing import Process
|
|
|
num = 100
|
|
|
def run1():
|
|
|
print("孙子进程开始...")
|
|
|
print("孙子进程结束...%s"%(num))
|
|
|
|
|
|
def run():
|
|
|
print("子进程开始...")
|
|
|
global num
|
|
|
num += 1
|
|
|
print(num)
|
|
|
p = Process(target=run1)
|
|
|
p.start()
|
|
|
p.join()
|
|
|
print("子进程结束...")
|
|
|
|
|
|
if __name__ == '__main__':
|
|
|
print("父进程开始...")
|
|
|
p = Process(target=run)
|
|
|
p.start()
|
|
|
p.join()
|
|
|
num += 2
|
|
|
# 在子进程中修改全局变量 对父进程中的全局变量没有影响
|
|
|
# 我们在创建子进程的时候 对全局变量做了一个备份
|
|
|
# 子进程和父进程的Num是两个完全不同的变量
|
|
|
# 所有进程对全局变量的修改 都不会影响其它进程
|
|
|
print("父进程结束...%d"%(num))
|
|
|
|
|
|
```
|
|
|
|
|
|
### 进程池
|
|
|
|
|
|
```python
|
|
|
from multiprocessing import Pool,Process
|
|
|
import time,random
|
|
|
def foo():
|
|
|
print("孙子进程开始...")
|
|
|
print("孙子进程结束...")
|
|
|
def func(__name__):
|
|
|
print("子进程%s启动..."%(__name__))
|
|
|
start = time.time()
|
|
|
time.sleep(random.choice([1,2,3]))
|
|
|
end = time.time()
|
|
|
print("子进程%s结束...耗时%.2f"%(__name__,end - start))
|
|
|
|
|
|
if __name__ == '__main__':
|
|
|
print("父进程开始...")
|
|
|
# 创建进程池
|
|
|
# 如果没有参数 默认大小为自己电脑的CPU核心数
|
|
|
# 表示可以同时执行的进程数量
|
|
|
pp = Pool(2)
|
|
|
for i in range(4):
|
|
|
# 创建进程,放入进程池统一管理
|
|
|
pp.apply_async(func,args=(i,))
|
|
|
# 在调用join之前必须先关掉进程池
|
|
|
# 进程池一旦关闭 就不能再添加新的进程了
|
|
|
pp.close()
|
|
|
# 进程池对象调用join,会等待进程池中所有的子进程结束之后再结束父进程
|
|
|
pp.join()
|
|
|
print("父进程结束...")
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
# 多线程:
|
|
|
|
|
|
在一个进程内部,要同时干很多事,就需要同时执行多个子任务
|
|
|
那么我们把进程内的这些子任务叫做线程
|
|
|
|
|
|
线程的内存空间是共享的 每个线程都共享同一个进程的资源
|
|
|
|
|
|
模块:
|
|
|
1、_thread模块 低级模块
|
|
|
2、threading模块 高级模块 对_thread模块进行了封装
|
|
|
"""
|
|
|
### 创建线程
|
|
|
|
|
|
```python
|
|
|
import threading,time
|
|
|
|
|
|
def run(num):
|
|
|
print("子线程%s开始..."%(threading.current_thread().__name__))
|
|
|
time.sleep(2)
|
|
|
print(num)
|
|
|
time.sleep(2)
|
|
|
# current_thread 返回一个当前线程的实例
|
|
|
print("子线程%s结束..."%(threading.current_thread().__name__))
|
|
|
if __name__ == '__main__':
|
|
|
print("主线程%s启动..."%(threading.current_thread().__name__))
|
|
|
# 创建子线程
|
|
|
t = threading.Thread(target = run,args = (1,))
|
|
|
t.start()
|
|
|
t.join()
|
|
|
print("主线程%s结束..."%(threading.current_thread().__name__))
|
|
|
|
|
|
```
|
|
|
|
|
|
### 多线程共享资源
|
|
|
|
|
|
```python
|
|
|
import threading
|
|
|
|
|
|
num = 0
|
|
|
var = 0
|
|
|
def run(n):
|
|
|
global num
|
|
|
for i in range(1000000):
|
|
|
num += n
|
|
|
num -= n
|
|
|
def run1(n):
|
|
|
global var
|
|
|
for i in range(100):
|
|
|
var += n
|
|
|
var -= n
|
|
|
|
|
|
if __name__ == '__main__':
|
|
|
t1 = threading.Thread(target=run,args=(6,))
|
|
|
t2 = threading.Thread(target=run,args=(9,))
|
|
|
t3 = threading.Thread(target=run,args=(5,))
|
|
|
t3.start()
|
|
|
t1.start()
|
|
|
t2.start()
|
|
|
t1.join()
|
|
|
t2.join()
|
|
|
t3.join()
|
|
|
print("num = %s"%(num))
|
|
|
|
|
|
```
|
|
|
|
|
|
### 互斥锁
|
|
|
|
|
|
```python
|
|
|
import threading
|
|
|
|
|
|
创建锁对象
|
|
|
|
|
|
lock = threading.Lock()
|
|
|
num = 0
|
|
|
|
|
|
def run(n):
|
|
|
global num
|
|
|
for i in range(1000000):
|
|
|
# 加锁 为了确保下面代码只能由一个线程从头到尾的执行
|
|
|
# 会阻止多线程的并发执行,所以效率会大大降低
|
|
|
"""
|
|
|
lock.acquire()
|
|
|
try:
|
|
|
num = num - n
|
|
|
num = num + n
|
|
|
finally:
|
|
|
# 解锁
|
|
|
lock.release()
|
|
|
"""
|
|
|
with lock:
|
|
|
num = num + n
|
|
|
num = num - n
|
|
|
|
|
|
if __name__ == '__main__':
|
|
|
t1 = threading.Thread(target=run,args=(6,))
|
|
|
t2 = threading.Thread(target=run,args=(9,))
|
|
|
t1.start()
|
|
|
t2.start()
|
|
|
t1.join()
|
|
|
t2.join()
|
|
|
print("num = %s"%(num))
|
|
|
|
|
|
```
|
|
|
|