python 20 Process类、进程锁、模拟抢票

day 20 Process类、进程锁、模拟抢票

昨日回顾

1.基于socket写TCP的客户端和服务端
	-加入链接循环
	-加入通信循环
	-客户端主动断开——> 服务端一直收空
	-客户端强制断开——> 服务端会报错
	-同一时刻,只能有一个客户端与服务端交互
2.基于UDP的客户端和服务端
	-数据不可靠,应用场景比较少
3.并发编程(进程、线程、协程)
4.进程:
	-资源分配的最小单位,线程是cpu调度的最小单位
	-食谱:程序
	-拿到食谱做饭的过程,叫进程
	-进程:程序运行的过程,一堆数据+做一件事的过程的集合
5.python中如何开启进程
	-multiprocessing中的Process
	-	# 开一个进程,执行task函数
    	p = Process(target=task)
    	# 进程执行起来(开启一个进程执行,需要时间)
    	p.start()
	

今日内容

1.进程调度算法(了解)

-先来先服务调度算法
-短作业优先调度算法
-时间片轮转法
-多级反馈队列

2.同步异步,阻塞非阻塞(了解)

1.同步调用:提交了以后,一直等待结果返回
2.异步调用:提交了以后,返回一个标志,等执行完成后,有消息通知

3.同步,异步:指的是消息通知机制
4.阻塞,非阻塞:程序在等待调用结果的状态
5.同步阻塞:打电话买书,没挂电话,一直在等待
6.同步非阻塞:打电话买书,没挂电话,一边干别的,一边听一下电话
7.异步阻塞:打电话买书,电话先挂了,等老板回电话,而自己则一直在电话旁等待老板回
8.异步非阻塞:打电话买书,电话挂了,等老板回电话,自己去干别的事。

3.Process类的参数(重点)

from multiprocessing import Process


def task(name, age):
    print(name)
    print(age)


if __name__ == '__main__':
    p = Process(target=task, args=('lem', 18))
    p.start()
    print(p.name)
    # group=None,
    # target=None,   要执行的任务,函数
    # name=None,   进程名
    # args=(),   以位置参数给任务(函数)传递参数
    # kwargs={}, 以关键字参数给任务(函数)传递参数

4.Process类的方法,属性(重点)

p = Process(target=task, args=('lem', 18))
p.start()  # 启动进程,必须调用start
p.run()  # 实际进程在执行的时候,执行的是run方法,但是调用run不会开进程
p.join()  # 主进程等待子进程执行完成
p.terminate()  # 通知操作系统去杀死p这个进程,需要时间
p.is_alive()  # 查看进程是否存活

print(p.name)  # 进程名
print(p.pid)  # 进程id号
p.daemon = True  # 主进程结束,子进程也结束,必须在start之前调用
    

主进程和子进程的进程号

from multiprocessing import Process
import os

def task(name, age):

    print("p进程的id号",os.getpid())  # 当前进程id号
    print("p进程的父进程也就是主进程的id号",os.getppid())  # 当前进程父进程id号




if __name__ == '__main__':
    p = Process(target=task, args=('lem', 18))
    p.start()
    print("p进程的id号",p.pid)
    print("主进程的id号",os.getpid())
    print("主进程的父进程的id号(pycharm)",os.getppid())

    
def task1(i):
    time.sleep(1)
    print("task1", i)


if __name__ == '__main__':
    t1 = time.time()
    ll = []
    for i in range(5):
        p1 = Process(target=task1, args=(i,))
        p1.start()
        ll.append(p1)

    for p in ll:
        p.join()

    print("主进程")
    print(time.time()-t1)

"""
开启多个进程,
如果想等待多个进程同时执行完,先把进程开启完成,再统一join
"""

开启进程的另一种方式

import time
from multiprocessing import Process
import os

# 另一种开启进程的方式
# 通过继承Process类的方式来实现,重写run方法

class MyProcess(Process):
    def __init__(self, name1, age):
        super().__init__()
        self.name1 = name1
        self.age = age

    def run(self) -> None:
        time.sleep(2)
        print(self.name1)
        print(self.name)
        print(self.age)


if __name__ == '__main__':
    p = MyProcess('lem', 18)
    p.start()  # 调用p.start(),不要调用run()

进程间的数据是隔离的

import time
from multiprocessing import Process
import os


def task():
    print("task")
    global n
    n = 100
    print("子进程", n)


if __name__ == '__main__':
    n = 10  # 在主进程定义n=10

    ## 如果这样写,n会被改掉
    # task()
    # print(n)

    p = Process(target=task)
    p.start()
    print("主进程", n)

5.进程同步(进程锁)(次重点)

import json
import time
from multiprocessing import Process, Lock


# 不加锁

# 查询票剩余数量
def check(i):
    with open('ticket', 'r') as f:
        data = json.load(f)
    print(f"{i}正在查票,票的剩余数量为{data['count']}张")
    if data['count'] > 0:
        return data


def write(dic):
    with open('ticket', 'w') as f:
        json.dump(dic, f)


# 抢票,票的数量减一
def buy(i):
    data = check(i)
    time.sleep(1)  # 模拟查票延迟
    if data:
        data['count'] -= 1
        time.sleep(1)  # 模拟买票延迟
        write(data)
        print(f"{i}购票成功")
    else:
        print(f"{i}购票失败")


def task(i, lock):
    res = check(i)
    if res:
        lock.acquire()
        buy(i)
        lock.release()


if __name__ == '__main__':
    lock = Lock()
    for i in range(10):
        p = Process(target=task, args=(i, lock))
        p.start()
posted @ 2021-04-26 15:42  橘丶阳菜  阅读(102)  评论(0编辑  收藏  举报