专栏首页Python 学习day37(多进程)- 多进程、守护进程、进程锁
原创

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

1.多进程示例

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

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

1.1 方法一,基于函数:

ffrom multiprocessing import Process
import os


def action(pName):
    print(pName)


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

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

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

    print(555)

1.2 方法二,继承:

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

from multiprocessing import Process
import os


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 = MyProcess('-->{}'.format(i))
        p_list.append(p)
        p.start()
    for p in p_list:
        p.join()

1.3 关于进程的数据隔离

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

from multiprocessing import Process
import socket


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

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


if __name__ == '__main__':
    sk = socket.socket()
    sk.bind(('127.0.0.1', 8000))
    sk.listen(1024)
    while 1:
        # 来一个请求接收一个
        # 没有请求就会阻塞在这里等待请求的到来
        conn, addr = sk.accept()
        socketProcess = MyMultiSocketProcess(conn, addr)
        socketProcess.start()

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

import socket

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

while 1:
    msgToClient = input('给服务端发消息>>>')
    socket_obj.send(msgToClient.encode('utf8'))
    msgFromServer = socket_obj.recv(1024).decode('utf8')
    print('msgFromServer:', msgFromServer)
    if msgFromServer == 'q':
        break
socket_obj.close()

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

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

from multiprocessing import Process
import time


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


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

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

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

from multiprocessing import Process
import time


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


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

5.关于如何使用进程锁

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

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

# lock.acquire(),上锁

# lock.release(),解锁

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

from multiprocessing import Process, Lock
import time


def work(pro, lock):
    # 上锁
    # 本质上多进程的时候,阻塞其他进程,只允许一个进程操作
    print(pro, '到门口了')
    lock.acquire()
    print(pro, '进来干了一些事儿')
    time.sleep(5)
    # 解锁
    lock.release()
    print(pro, '出去了')


if __name__ == '__main__':
    lock_obj = Lock()
    p_1 = Process(target=work, args=('进程_1', lock_obj))
    p_2 = Process(target=work, args=('进程_2', lock_obj))
    p_3 = Process(target=work, args=('进程_2', lock_obj))
    p_1.start()
    p_2.start()
    p_3.start()
    p_1.join()
    p_2.join()
    p_3.join()

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

from multiprocessing import Process, Lock
import time


def work(pro, lock):
    # 上锁
    # 本质上多进程的时候,阻塞其他进程,只允许一个进程操作
    print(pro, '到门口了')
    lock.acquire()
    print(pro, '拿到锁干了一些事儿')
    time.sleep(5)
    # 解锁
    lock.release()
    print(pro, '还了锁出去了')


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


def work2(pro, lock):
    print('in work2')
    work(pro, lock)


def work3(pro, lock):
    print('in work3')
    work(pro, lock)


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

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

原创声明,本文系作者授权云+社区发表,未经许可,不得转载。

如有侵权,请联系 yunjia_community@tencent.com 删除。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • day38(多进程) - 信号量、事件、进程队列(进程之间的通信)

    # 进程 A 将 event.clear()之后,进程 B 遇到 wait() 立即进入阻塞

    少年包青菜
  • day94-认证组件&权限组件&访问评率限制

    1.1.3 返回值返回两个参数,request.user 和 request.auth,即 user_obj 和 token

    少年包青菜
  • 前端-part4-JavaScript字符串+数组+循环

    少年包青菜
  • 进程(一)

    py3study
  • python3--队列Queue,管道Pipe,进程之间的数据共享,进程池Pool,回调函数callback

    既打印了主进程put的值,也打印了子进程put的值,在进程中使用队列可以完成双向通信

    py3study
  • python高阶教程-上下文管理器

    本文由腾讯云+社区自动同步,原文地址 http://blogtest.stackoverflow.club/book/senior_python/context...

    羽翰尘
  • python3–循环语句

    老七Linux
  • Numpy教程第1部分 - 阵列简介(常用基础操作总结)

    【导读】这里是numpy教程的基础部分,涵盖了使用numpy的ndarrays执行数据操作和分析的一些操作。众所周知,Numpy是Python中最基本和最强大的...

    WZEARW
  • 第四冠!腾讯AI「绝艺」斩获世界智能围棋公开赛冠军

    ? 导语:腾讯围棋AI「绝艺」世界大赛再夺金,三年四冠,砥砺前行! ? 中国围棋协会主办的2019「中信建投证券杯」世界智能围棋公开赛今天在山东日照落幕。由腾...

    腾讯技术工程官方号
  • Numpy中的转置轴对换

    转置是重塑的一种特殊形式。转置返回源数组的视图,源数组和对源数组进行转置操作后返回的数组指向的是同一个地址。Numpy中有三种方式能够对数组进行转置操作:

    触摸壹缕阳光

扫码关注云+社区

领取腾讯云代金券