265 lines
6.2 KiB
Markdown
265 lines
6.2 KiB
Markdown
# 多任务介绍
|
||
什么是多任务?
|
||
操作系统可以同时执行多个任务
|
||
|
||
现在的操作系统: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))
|
||
|
||
```
|
||
|