### 9.4 Process模块 进程
```python
from multiprocess import Process
p = Process(target=函数名,args=(参数1,))
1.如何创建一个进程对象
对象和进程之间的关系:
a.进程对象和进程并没有直接的关系
b.只是存储了一些和进程相关的内容
c.此时此刻,操作系统还没有接收到创建进程的指令
2.如何开启一个进程
通过p.start()开启一个进程,这个方法相当于给操作系统一个开启指令指令
start方法的异步非阻塞的特点:
a.在执行这个方法的时候,我们既不等待进程开启,也不等待操作系统给我们的想要
b.这里只是负责同志操作系统去开启一个进程
开启一个子进程之后,主进程和子进程的代码完全异步
3.父进程和子进程之间的关系
a.父进程会等待子进程结束之后才结束
b.是为了挥手子进程的资源
4.不同操作系统中进程开启的方式
windows 通过(模块导入)再一次执行父进程文件中的代码来获取父进程中的数据
所以只要是不希望被子进程执行的代码,就写在if __name__ == '__main__'下
因为在进行导入的时候父进程文件中的__name__ != '__main__'
linux/ios
正常的写就可以,没有if __name__ == '__main__'这件事情了
5.如何确认一个子进程执行完毕
join方法
开启了多个子进程,等待所有子进程结束
```
#### 9.4.1 守护进程
```python
def son1(a,b):
while True:
print('is alive')
time.sleep(0.5)
def son2():
for i in range(5):
print('in son2')
time.sleep(1)
if __name__ == "__main__":
p = PROcess(target=son1,args=(1,2))
p.daemon = True
p.start()
p2 = Process(target=son2)
p2.start()
time.sleep(2)
#守护进程是随着主进程的代码结束而结束
生产者消费者模型的时候
守护线程做对比的时候
#所有子进程都必须在主进程结束之前结束,由主进程挥手资源
```
```python
# 有一个参数可以把一个子进程设置为一个守护进程
import time
from multiprocessing import Process
def son1():
while True:
print('is alive')
time.sleep(0.5)
if __name__ == '__main__':
p = Process(target=son1)
p.start() # 异步 非阻塞
print(p.is_alive())
time.sleep(1)
p.terminate() # 异步的 非阻塞
print(p.is_alive()) # 进程还活着 因为操作系统还没来得及关闭进程
time.sleep(0.01)
print(p.is_alive()) # 操作系统已经响应了我们要关闭进程的需求,再去检测的时候,得到的结果是进程已经结束了
# 什么是异步非阻塞?
# terminate
```
#### 9.4.2 面向对象方式的守护进程
#### 9.4.3 Process类的总结
```python
# Process类
# 开启进程的方式
# 面向函数
# def 函数名:要在子进程中执行的代码
# p = Process(target= 函数名,args=(参数1,))
#面向对象
#class 类名(Process):
#def __init__(self,参数1,参数2):
#self.a = 参数1
#self.b = 参数2
#super().__init__()
#def run(self):
#需要在紫禁城中执行的代码
#p = 类名(参数1,参数2)
#p.start() 异步非阻塞
#p.terminate() 异步非阻塞
#p.join() 同步阻塞
#p.isalive() 获取当前进程状态
#daemon = True 设置为守护进程,守护进程会在主进程代码结束后结束
```
####
### 9.5 锁
#### 9.5.1 什么时候需要用锁
- 如果在一个并发条件下,涉及的某部分内容
- 是需要修改一些所有进程共享的数据资源
- 需要枷锁类维持数据的安全
- 在数据安全的基础上,才考虑效率问题
- 同步存在的意义
- 数据安全
#### 9.5.2 锁在代码中的应用顺序
- 在主进程中实例化lock = Lock()
- 把这把锁传递给子进程
- 在子进程中 对需要枷锁的代码进行with lock:
- with lock 相当于lock.acquire()和lock.release()
- 在主进程需要加锁的场景:
- 共享数据资源(文件、数据等)
- 对资源进行修改删除操作
- 加锁之后能保证数据的安全性 但同时也降低了程序的执行效率
```python
import time
import json
from multiprocessing import Process,Lock
def search_ticket(user):
with open('ticket_count') as f:
dic = json.load(f)
print('%s查询结果 : %s张余票'%(user,dic['count']))
def buy_ticket(user,lock):
# with lock:
# lock.acquire() # 给这段代码加上一把锁
time.sleep(0.02)
with open('ticket_count') as f:
dic = json.load(f)
if dic['count'] > 0:
print('%s买到票了'%(user))
dic['count'] -= 1
else:
print('%s没买到票' % (user))
time.sleep(0.02)
with open('ticket_count','w') as f:
json.dump(dic,f)
# lock.release() # 给这段代码解锁
def task(user, lock):
search_ticket(user)
with lock:
buy_ticket(user, lock)
if __name__ == '__main__':
lock = Lock()
for i in range(10):
p = Process(target=task,args=('user%s'%i,lock))
p.start()
```
#### 9.5.3 进程之间的通信(IPC)
```python
# 通信
#进程之间的通信 - IPC(inter process communication)
from multiprocessing import Queue,Process
# 先进先出
def func(exp,q):
ret = eval(exp)
q.put({ret,2,3})
q.put(ret*2)
q.put(ret*4)
if __name__ == '__main__':
q = Queue()
Process(target=func,args=('1+2+3',q)).start()
print(q.get())
print(q.get())# print(q.get())
# Queue基于 天生就是数据安全的
# 文件家族的socket pickle lock
# pipe 管道(不安全的) = 文件家族的socket pickle
# 队列 = 管道 + 锁
```