## 什么是进程
程序并不能单独运行,只有将程序装载到内存中,系统为它分配资源才能运行,而这种执行的程序就称之为进程。程序和进程的区别就在于:程序是指令的集合,它是进程运行的静态描述文本;进程是程序的一次执行活动,属于动态概念。在多道编程中,我们允许多个程序同时加载到内存中,在操作系统的调度下,可以实现并发地执行。这是这样的设计,大大提高了CPU的利用率。进程的出现让每个用户感觉到自己独享CPU,因此,进程就是为了在CPU上实现多道编程而提出的。
## 多道程序设计技术
所谓多道程序设计技术,就是指允许多个程序同时进入内存并运行。即同时把多个程序放入内存,并允许它们交替在CPU中运行,它们共享系统中的各种硬、软件资源。当一道程序因I/O请求而暂停运行时,CPU便立即转去运行另一道程序。
## 多进程
实例(可以循环生成多个子进程)
~~~
from multiprocessing import Process
def f(name):
print('hello', name)
if __name__ == '__main__':
p = Process(target=f, args=('bob',)) #生成一个子进程
p.start() #启动一个子进程
p.join() #等待子进程的执行结束
~~~
## 多进程间的通讯
由于多进程与多线程不同,多线程是处在同一个进程之间,所以多线程之间的内存是共享的,他们可以修改同一个内存中的数据,可以相互之间达到内存共享。但是多进程则不同,多进程之间由于内存独立,所以数据之间不能直接共享,那么我们如何实现多进程之间的通讯呢?
### 一、Queue队列
~~~
from multiprocessing import Queue,Process
def func(a):
print('这是子进程:',a.get())
if __name__ == '__main__':
q = Queue()
q.put(123)
p = Process(target=func,args=(q,))
p.start()
运行结果:
>>这是子进程: 123
~~~
进程Queue和线程queue的使用方法基本一致,但是我们在父进程中放入Queue中的数据可以在子进程中拿出(反之也可以),这种方法实现了进程间的数据传递。
### 二、**Pipes管道**
~~~
from multiprocessing import Process,Pipe
def func(n):
print(n.recv())
n.send('from son')
if __name__ == '__main__':
f,s = Pipe()
p = Process(target=func,args=(s,))
p.start()
f.send('from father')
print(f.recv())
~~~
实例化管道之后,会返回两个对象,也就是管道的两端,将一端留在父进程,一端作为参数传入给子进程,然后可以通过send和recv方法接收和发送数据,以达到不同进程间的通信。
### 三、**Managers**
~~~
from multiprocessing import Process,Manager
import os
def func(a,b):
a[os.getpid()] = os.getpid()
b.append(os.getpid())
if __name__ == '__main__':
manager = Manager()
d = manager.dict()
l = manager.list()
l2 = []
for i in range(10):
p = Process(target=func,args=(d,l))
p.start()
l2.append(p)
for i in l2:
i.join()
# os.getpid()是获得当前进程的id,os.getppid()是获得当前父进程的id
~~~
实例化manager之后。通过manager来生成字典,列表等等,将其传给子进程,通过这些数据格式来实现不同进程间的通讯。A manager returned by Manager() will support types **`list`, `dict`, `Namespace`, `Lock`, `RLock`, `Semaphore`, `BoundedSemaphore`, `Condition`, `Event`, `Barrier`, `Queue`, `Value` and `Array`. **
## 进程锁
```
from multiprocessing import Process, Lock
def f(l, i):
l.acquire()
print('hello world', i)
l.release()
if __name__ == '__main__':
lock = Lock()
for num in range(10):
Process(target=f, args=(lock, num)).start()
进程锁
```
有人说,线程之间加锁是为了避免数据混乱,进程之间内存都已经不共享了,为什么还要加锁呢?如果多个进程同时占有对方需要的资源而同时请求对方的资源,而它们在得到请求之前不会释放所占有的资源,那么就会导致死锁的发生,也就是进程不能实现同步。举个例子就是竞争资源,如当系统中供多个进程共享的资源如打印机、公用队列等,其数目不足以满足进程的需要时,会引起诸进程的竞争而产生死锁。
## 进程池
进程池内部维护一个进程序列,当使用时,则去进程池中获取一个进程,如果进程池序列中没有可供使用的进进程,那么程序就会等待,直到进程池中有可用进程为止。
进程池中的方法:
* apply 从进程池里取一个进程并同步执行
* apply\_async 从进程池里取出一个进程并异步执行
* terminate 立刻关闭进程池
* join 主进程等待所有子进程执行完毕,必须在close或terminete之后
* close 等待所有进程结束才关闭线程池
~~~
from multiprocessing import Pool
import time,os
def Foo(i):
time.sleep(2)
print('进程:',os.getpid())
return 'ok' #return的值被回调函数接收
def Bar(arg):
print('-->该子进程执行完毕:', arg,os.getpid()) #由执行结果可以发现回调函数由父进程执行而不由子进程执行
if __name__ == '__main__':
print('父进程:',os.getpid())
pool = Pool(5)
for i in range(10):
pool.apply_async(func=Foo, args=(i,), callback=Bar) #程序异步执行,也就是并行,Bar为回调函数,可以没有
# pool.apply(func=Foo, args=(i,)) #如果执行这种方法,程序会变成同步执行,也就是串行
pool.close()
pool.join() # 进程池中进程执行完毕后再关闭,如果注释,那么程序直接关闭。
~~~
```
父进程: 904
进程: 12232
-->exec done: ok 904
进程: 14396
-->exec done: ok 904
进程: 16736
-->exec done: ok 904
进程: 17276
-->exec done: ok 904
进程: 2908
-->exec done: ok 904
进程: 12232
-->exec done: ok 904
进程: 14396
-->exec done: ok 904
进程: 16736
-->exec done: ok 904
进程: 17276
-->exec done: ok 904
进程: 2908
-->exec done: ok 904
执行结果
```
- Python学习
- Python基础
- Python初识
- 列表生成式,生成器,可迭代对象,迭代器详解
- Python面向对象
- Python中的单例模式
- Python变量作用域、LEGB、闭包
- Python异常处理
- Python操作正则
- Python中的赋值与深浅拷贝
- Python自定义CLI三方库
- Python并发编程
- Python之进程
- Python之线程
- Python之协程
- Python并发编程与IO模型
- Python网络编程
- Python之socket网络编程
- Django学习
- 反向解析
- Cookie和Session操作
- 文件上传
- 缓存的配置和使用
- 信号
- FBV&&CBV&&中间件
- Django补充
- 用户认证
- 分页
- 自定义搜索组件
- Celery
- 搭建sentry平台监控
- DRF学习
- drf概述
- Flask学习
- 项目拆分
- 三方模块使用
- 爬虫学习
- Http和Https区别
- 请求相关库
- 解析相关库
- 常见面试题
- 面试题
- 面试题解析
- 网络原理
- 计算机网络知识简单介绍
- 详解TCP三次握手、四次挥手及11种状态
- 消息队列和数据库
- 消息队列之RabbitMQ
- 数据库之Redis
- 数据库之初识MySQL
- 数据库之MySQL进阶
- 数据库之MySQL补充
- 数据库之Python操作MySQL
- Kafka常用命令
- Linux学习
- Linux基础命令
- Git
- Git介绍
- Git基本配置及理论
- Git常用命令
- Docker
- Docker基本使用
- Docker常用命令
- Docker容器数据卷
- Dockerfile
- Docker网络原理
- docker-compose
- Docker Swarm
- HTML
- CSS
- JS
- VUE