-
代码创建进程
-
join方法
-
进程间数据默认隔离
-
进程对象相关属性和方法
-
僵尸进程和孤儿进程
-
守护进程
-
互斥锁
一、代码创建进程
"""
1.创建进程的方式
鼠标双击桌面一个应用图标
代码创建
创建进程的本质:
在内存中要一块内存空间用来运行相应的程序代码
"""
# multiprocessing 进程模块
# Process P是大写
from multiprocessing import Process
import time
def task(name):
print('%s is runing'% name)
time.sleep(3)
print('%s is over'% name)
if __name__ == '__main__':
p = Process(target=task, args= ('owen', ))
p.start()
print('主进程')

from multiprocessing import Process
import time
class MyProcess(Process):
def __init__(self, username):
self.username =username
super().__init__()
def run(self):
print('嘿喽哇', self.username)
time.sleep(3)
print('再会', self.username)
if __name__ == '__main__':
p = MyProcess('owen')
p.start()
print('主进程')

# 它的实现就是将于客户端通信的代码封装称为一个函数, 之后来一个客户就创建一个进程,专门服务
# 服务端
import socket
from multiprocessing import Process
def get_server():
server = socket.socket()
server.bind(('127.0.0.1', 9999))
server.listen(5)
return server
# 将服务客户端的代码封装成函数(通信代码)
def talk(sock):
while True:
data = sock.recv(1024)
print(data.decode('utf8'))
sock.send(data.upper()) # 接收值发送大写
if __name__ == '__main__':
server = get_server()
while True:
sock, addr = server.accept()
p = Process(target=talk, args=(sock, ))
p.start()
# 客户端
import socket
client = socket.socket()
client.connect(('127.0.0.1', 9999))
while True:
client.send(b'hello')
data = client.recv(1024)
print(data.decode('utf8'))
二、join方法
# join方法就是让主进程等待子进程代码运行完毕之后 再执行
from multiprocessing import Process
import time
def task(name, n):
print(f'{name} is running')
time.sleep(n)
print(f'{name} is over')
if __name__ == '__main__':
p1 = Process(target=task, args=('cuihua', 1))
p2 = Process(target=task, args=('xiongda', 2))
p3 = Process(target=task, args=('guangtouqiang', 3))
start_time = time.time()
p1.start()
p2.start()
p3.start()
p1.join()
p2.join()
p3.join()
end_time = time.time() - start_time
print('主进程', f'总耗时:{end_time}')
# 主进程 总耗时:3.0834152698516846

如果想要p.start()之后的代码, 等待子进程全部运行结束之后再打印
1.直接sleep,但是这个方法肯定不可行,因为子进程运行时间不可控
2.join方法
针对多个子进程的等待
三、进程间数据默认隔离
# 我们可以把内存看成很对个小房间组成的, 一人一个互不干扰
from multiprocessing import Process
money = 100
def task():
global money # 局部改全局申明
money = 222
if __name__ == '__main__':
p = Process(target=task)
p.start()
p.join()
print(money)
# 同一台计算机上面,进程和进程之间是数据隔离的

四、进程对象属性和方法
"""
查看进程号的方法:
windows: tasklist 结果集中PID
mac: ps -ef
"""
1.1、查看进程号
courrent_process函数
from multiprocessing import Process, current_process
print(current_process().pid) # 13236
# 获取进程号的目的就是可以通过代码的方式管理进程
windows系统: taskkill关键字
Mac/linux系统: kill关键字
1.2、os模块
os.getpid() # 获取当前进程的进程号
os.getppid() # 获取到当前进程的父进程号
2.杀死子进程
terminate() # 这个过程可能需要一点时间
3.判断子进程是否存活
is_alive() # 返回True或者False
五、僵尸进程和孤儿进程
僵尸进程
所有的子进程在运行结束之后都会编程僵尸进程(死了没死透)
因为还保留着pid和一些运行过程的中的记录便于主进程查看(只是短时间保存)
等这些信息被主进程回收,就彻底死了
1.主进程正常结束
2.调用join方法
# 僵尸进程是无害的
孤儿进程
# 子进程存在,但是父进程毙了
子进程会被操作系统自动接管
六、守护进程
"""
守护就是生死全靠守护的对象,对生守生, 对死守死
"""
from multiprocessing import Process
import time
def task(name):
print(f'御用特使:{name}还没死')
time.sleep(3)
print(f'御用特使:{name}死了')
if __name__ == '__main__':
p = Process(target=task, args=('黑大帅', ))
p.daemon = True # 将子进程设置为守护进程,主进程结束,子进程立即结束
p.start()
print('皇上毙了')
# p.daemon = True 一定要放在p.start()上面
七、互斥锁*
import json
from multiprocessing import Process
import time
import random
# 设置票数,一张
ticket_data.json : {"ticket_num": 1}
# 查票功能
def search(name):
with open(r'ticket_data.json', 'r', encoding='utf8') as f:
data = json.load(f)
print(f'{name}查询余额为:%s'% data.get('ticket_num'))
# 买票功能
def buy(name):
# 先查一下票数
with open(r'ticket_data.json', 'r', encoding='utf8') as f:
data = json.load(f)
time.sleep(random.randint(1, 3)) # 停留1~3秒
# 判断
if data.get('ticket_num') > 0:
data['ticket_num'] -= 1
with open(r'ticket_data.json', 'w', encoding='utf8') as f:
json.dump(data, f)
print(f'{name}抢票成功')
else:
print(f'{name}抢票失败,票已经没了')
# 将买票封装成函数
def run(name):
search(name)
buy(name)
# 模拟多人同时
if __name__ == '__main__':
for i in range(1, 6):
p = Process(target=run, args=('用户:%s' % i, ))
p.start()
用户:2查询余额为:2
用户:1查询余额为:2
用户:3查询余额为:2
用户:5查询余额为:2
用户:4查询余额为:2
用户:4抢票成功用户:5抢票成功
用户:2抢票成功
用户:1抢票成功
用户:3抢票成功
# 结果很明显,是错乱的,而且都5个人买一张都成功了
"""
在多个进程操作同一个数据的时候会造成数据的错乱, 所以我们需要增加一个加锁处理(互斥锁)
将并发变成串行, 效率低了,但安全性高了
互斥锁并不能轻易使用, 容易造成死锁现象
互斥锁旨在处理数据的部分加锁, 不能什么地方都加
"""
# 增加互斥锁
from multiprocessing import Process, Lock
mutex = Lock()
mutex.acquire() # 上锁
mutex.release() # 解锁
# 将买票封装成函数
def run(name,mutex):
search(name)
mutex.acquire() # 上锁
buy(name)
mutex.release() # 解锁
# 模拟多人同时
if __name__ == '__main__':
mutex = Lock()
for i in range(1, 6):
p = Process(target=run, args=('用户:%s' % i, mutex))
p.start()
用户:1查询余额为:2
用户:2查询余额为:2
用户:3查询余额为:2
用户:4查询余额为:2
用户:5查询余额为:2
用户:1抢票成功
用户:2抢票成功
用户:3抢票失败,票已经没了
用户:4抢票失败,票已经没了
用户:5抢票失败,票已经没了
"""
行锁: 针对行数加锁, 同一时间只能一个人操作
表锁: 针对表数据加锁, 同一时间只能一个人操作
"""
