day37(多进程)- 多进程、守护进程、进程锁

2020-12-14 11:44:10 浏览数 (1)

1.多进程示例

# join(),程序执行到这里会等待子程序运行完毕才会继续运行主程序

# join(),在执行 .start() 之后写

1.1 方法一,基于函数:

代码语言:python代码运行次数:0复制
from multiprocessing import Process


def action(p_name):
    print(p_name)


if __name__ == '__main__':
    p_list = []

    for i in range(1, 100):
        # 注册函数进去内存
        p_obj = Process(target=action, args=('p_{}'.format(i),))
        p_list.append(p_obj)
        p_obj.start()

    for p_obj in p_list:
        # join(),程序执行到这里会等待子程序运行完毕
        # 下面的 over 会等这里的子进程执行完毕才会打印
        p_obj.join()

    print('over')

1.2 方法二,继承:

# obj.start() 实际上是用的 run() 方法 # 但是对象不能直接调用 run() 方法 # 直接调用就立即执行,成了单线程 # start() 是抛出进程到后台,形成多个进程, # 每个独立的进程各自调用 run() 方法

代码语言:javascript复制
from multiprocessing import Process


class MyProcess(Process):
    def __init__(self, ele, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.ele = ele

    # obj.start() 实际上是用的 run() 方法
    # 但是对象不能直接调用 run() 方法
    # 直接调用就立即执行,成了单线程
    # start() 是抛出进程到后台,形成多个进程,
    # 每个独立的进程各自调用 run() 方法
    def run(self) -> None:
        print(self.ele)


if __name__ == '__main__':
    p_list = []
    for i in range(1, 100):
        p_obj = MyProcess('进程-> {}'.format(i))
        p_list.append(p_obj)
        p_obj.start()
    for p_obj in p_list:
        p_obj.join()
    print('over')

1.3 关于进程的数据隔离

代码语言:php复制
from multiprocessing import Process
import os


def func():
    global n  # 2.子进程中把n声明尾全局变量
    n = 0  # 3.对n重写

    print('子进程号:', os.getpid(), ',n值是:', n)


if __name__ == '__main__':
    n = 100  # 1.父进程中什么一个n = 100
    p = Process(target=func)
    p.start()
    p.join()  # 4.等待子进程结束
    print('父进程号:', os.getpid(), ',n值是', n)
    
    # 运算结果如下,证明力子进程和父进程之间的数据内存是完全隔离的

数据隔离的结果:

子进程号: 10428 ,n值是: 0

父进程号: 11616 ,n值是 100

========================================================================================

2.关于如何实现多个client连接(与socketserver无关)

server端.py

代码语言:javascript复制
from multiprocessing import Process
import socket


class MyMultiSocketProcess(Process):
    def __init__(self, connection, address, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.connection = connection  # type: socket.socket
        self.address = address

    def run(self) -> None:
        while 1:
            msg_from_client = self.connection.recv(1024).decode('utf8')
            print(self.address, ':', msg_from_client)
            if msg_from_client == 'q':
                msg_to_client = '再见!'.encode('utf8')
                self.connection.send(msg_to_client)
                self.connection.close()
                break
            # 设置自动回复消息
            msg_to_client = '这是来自服务端的回复消息'.encode('utf8')
            self.connection.send(msg_to_client)


if __name__ == '__main__':
    sk = socket.socket()
    sk.bind(('127.0.0.1', 8000))
    sk.listen(1024)
    while 1:
        conn, addr = sk.accept()  # accept() 会等待请求,无请求时保持阻塞
        socketProcess = MyMultiSocketProcess(conn, addr)
        socketProcess.start()

client1 client2 client3 ...多个很多的客户端

代码语言:javascript复制
import socket

socket_obj = socket.socket()
# 连接请求
socket_obj.connect(('127.0.0.1', 8000))

"""服务端收发消息是 connection"""
"""客户端收发消息是 socket 对象"""
"""一收一发,夯住循环"""
while 1:
    msg_to_client = input('给服务端发消息>>>')
    socket_obj.send(msg_to_client.encode('utf8'))
    msg_from_server = socket_obj.recv(1024).decode('utf8')
    print('msg_from_server:', msg_from_server)
    if msg_from_server == 'q':
        break
socket_obj.close()

3.设置守护进程(子进程随着主进程的 代码 结束而结束)

# .daemon() 在 .start() 之前写

代码语言:python代码运行次数:0复制
from multiprocessing import Process
import time


def action():
    # 子进程无限循环
    while 1:
        print('我是子进程')
        time.sleep(0.5)


if __name__ == '__main__':
    p_obj = Process(target=action, args=())
    # 设置 .daemon = True,子进程跟着父进程一起死
    # 在 start() 之前写!!!
    p_obj.daemon = True
    p_obj.start()

    # 父进程有限循环
    for i in range(10):
        time.sleep(1)
        print('父进程')

4. is_alive()方法的使用和terminate() 方法的使用

代码语言:javascript复制
from multiprocessing import Process
import time


def action():
    # 子进程无限循环
    while 1:
        print('我是子进程')
        time.sleep(2)


if __name__ == '__main__':
    p_obj = Process(target=action, args=())
    p_obj.start()
    print('p进程是否存活->', p_obj.is_alive())
    time.sleep(5)
    # 杀死进程
    p_obj.terminate()
    # 为什么要休眠一秒,因为操作系统不会立即终结子进程
    time.sleep(1)
    print('p进程是否存活->', p_obj.is_alive())

5.关于如何使用进程锁

# 本质上多进程的时候,阻塞其他进程,只允许一个进程操作

# # # 任何进程只要使用了同一个锁对象,就全部都受这把锁的管理

# lock.acquire(),上锁

# lock.release(),解锁

5.1 多进程执行同一个函数,锁可以管控到(并发时访问同一个业务)

代码语言:javascript复制
from multiprocessing import Process, Lock
import time


def action(pro, lock):
    # 上锁
    # 本质上多进程的时候,阻塞其他进程,只允许一个进程操作
    print(pro, '进入了程序')
    lock.acquire()
    print(pro, '进来干了一些事儿')
    time.sleep(2)
    # 解锁
    lock.release()
    print(pro, '结束了程序')


if __name__ == '__main__':
    lock_obj = Lock()
    p_list = []
    for i in range(1, 10):
        p_obj = Process(target=action, args=('进程-> {}'.format(i), lock_obj))
        p_list.append(p_obj)
        p_obj.start()
    for p_obj in p_list:
        p_obj.join()

5.2 不同进程执行的都是执行不同的任务,使用了同一个锁对象,依然可以管控进程(并发时访问不同业务)

代码语言:javascript复制
from multiprocessing import Process, Lock
import time


def action(pro, lock):
    # 上锁
    # 本质上多进程的时候,阻塞其他进程,只允许一个进程操作
    print(pro, '进入了程序')
    lock.acquire()
    print(pro, '进来干了一些事儿')
    time.sleep(2)
    # 解锁
    lock.release()
    print(pro, '结束了程序')


# 多个进程子各自的函数内做自己的事儿
# 依然只能每次执行一个进程
def action1(pro, lock):
    print('in action1')
    action(pro, lock)


def action2(pro, lock):
    print('in action2')
    action(pro, lock)


def action3(pro, lock):
    print('in action3')
    action(pro, lock)


if __name__ == '__main__':
    p_list = []
    lock_obj = Lock()

    # p_1 执行的是 action1
    # p_2 执行的是 action2
    # p_3 执行的是 action3
    # 彼此不干扰
    # 测试结果发现 锁 依然可以管控
    p_1 = Process(target=action1, args=('进程_1', lock_obj))
    p_2 = Process(target=action2, args=('进程_2', lock_obj))
    p_3 = Process(target=action2, args=('进程_3', lock_obj))
    p_1.start()
    p_2.start()
    p_3.start()
    p_1.join()
    p_2.join()
    p_3.join()

0 人点赞