首页 > 编程语言 >并发编程

并发编程

时间:2022-11-18 20:48:06浏览次数:40  
标签:__ p1 name Process 编程 print 并发 进程

并发编程

同步与异步

用来表达任务的提交方式

  1. 同步

    提交完任务之后原地等待任务的返回结果期间不做任何事

    可靠任务序列

  2. 异步

    提交完任务后不等待任务的返回结果直接去做其他事情有结果自动通知,至被依赖的任务最终是否真正完成,依赖他的任务无法确定

    不可靠任务序列

阻塞与非阻塞

用来表达任务的运行状态

  1. 阻塞

    阻塞态,停住不执行,cpu被拿走

  2. 非阻塞

    就绪态、运行态

四种结合状态

  1. 同步阻塞
    效率最低,相当于单道

  2. 同步非阻塞
    按照顺序执行,但是不等待结果

  3. 异步阻塞
    不按照顺序执行,但是等待结果

  4. 异步非阻塞

    效率最高,既可以不按照顺序执行,也不等待结果

创建进程的多种方式

再不同的操作系统中创建进程底层原理不一样

  1. windows
    以导入模块的形式创建进程
  2. linux/mac
    以拷贝代码的形式创建进程

from multiprocessing import Process


# 第一种,继承Process类,派生直接的类


class MyProcess(Process):
    def __init__(self, num):
        super().__init__()
        self.num = num
        print(self.name)  # 输出进程的名称

    def run(self):
        print(self.pid)  # 输出进程的pid
        print('我是子进程', self.num)


if __name__ == '__main__':
    for i in range(5):
        p = MyProcess(i)
        p.start()


# 第二种手动创建

from multiprocessing import Process


def task(num):
    print('我是子进程', num)


if __name__ == '__main__':
    for i in range(5):
        p = Process(target=task, args=(i,))
        p.start()


# 第三种进程池

from concurrent.futures import ProcessPoolExecutor
import time

def task(num):
    print('我是子进程', num)
    time.sleep(1)


if __name__ == '__main__':
    with ProcessPoolExecutor(4) as pool:  # 进程池里面的最大数就是一次最多运行的进程
        for i in range(10):
            pool.submit(task, i)

进程间数据隔离

同一台计算机上的多个进程数据是严格意义上的物理隔离(默认情况)

from multiprocessing import Process

num = 1000

def task():
    global num
    num = 666
if __name__ == '__main__':
    p1 = Process(target=task)
    p1.start()
    import time

image

进程的join方法

from multiprocessing import Process
import time

def task():
    num = 666
    print('子进程',num)
    time.sleep(1)

if __name__ == '__main__':
    p1 = Process(target=task)
    p1.start()
    p1.join()  # 等待子进程运行完毕后才向下运行
    print('主进程')

image

IPC机制(进程间通信消息队列)

IPC:进程间通信

消息队列:存储数据的地方 所有人都可以存 也可以取

from multiprocessing import Process, Queue
def task1_put(queue):
    print(queue.get())  # 如过消息队列没有数据则会一直阻塞,等着有消息才会向下执行
    print(queue.get())  # 如过消息队列没有数据则会一直阻塞,等着有消息才会向下执行
    print(queue.empty())  # 看看消息是不是空的  多进程不会用,因为消息有滞后性
    print(queue.get())  # 如过消息队列没有数据则会一直阻塞,等着有消息才会向下执行
def task2_get(queue):
    queue.put('我是子进程放入的消息')
    print(queue.full())  # 看看消息是不是满的  多进程不会用,因为消息有滞后性
if __name__ == '__main__':
    queue = Queue()  # 不填默认数字很大,可以规定这个消息队列,最多能有多少消息同时存在
    queue.put('主进程存放数据')  # 如果队列存满则会阻塞,等着直到有空隙放入消息,才会向下执行
    p1 = Process(target=task1_put, args=(queue,))
    p2 = Process(target=task2_get, args=(queue,))
    p1.start()
    p2.start()

image

生产者消费者模型

  1. 生产者
    负责产生数据的人
  2. 消费者
    负责处理数据的人

该模型除了有生产者和消费者之外还必须有消息队列(只要是能够提供数据保存服务和提取服务的理论上都可以)

进程对象的多种方法

1.如何查看进程号

两种方式
# 方法1
from multiprocessing import current_process, Process


def task():
    print(current_process())
    print(current_process().pid, '子进程')
    """
    <Process name='Process-1'子进程的父进程pid parent=8432 started>
    18228 子进程
    """


if __name__ == '__main__':
    p1 = Process(target=task).start()
    print(current_process())
    print(current_process().pid, '父进程')
    """<_MainProcess name='MainProcess' parent=None started>
    8432 父进程"""

# 方法2

from multiprocessing import Process
import os


def task():
    print(os.getpid(), '子进程')
    print(os.getppid(), '子进程的父进程')
    """
    8276 子进程
    2020 子进程的父进程
    """


if __name__ == '__main__':
    p1 = Process(target=task).start()
    print(os.getpid(), '子进程')
    print(os.getppid(), 'pycharm进程')  # 获取了创建这个程序的pid,pycharm执行获取的就是pycharm pid
    """
    2020 子进程
    19664 pycharm进程
    """
2.终止进程
	p1 = Process(target=task)
    p1.start()
    p1.terminate()
    计算机操作系统都有对应命令可以直接杀死进程
3.判断进程是否存活
	p1 = Process(target=task)
    p1.start()
    p1.is_alive()
4.创建进程
	p1 = Process(target=task)
    p1.start()
5.等待子进程运行完毕
	p1 = Process(target=task)
    p1.start()
    p1.join()

守护进程

守护进程会随着守护的进程结束而立刻结束

from multiprocessing import Process
import time


def task(name):
    print('德邦总管:%s' % name)
    time.sleep(3)
    print('德邦总管:%s' % name)


if __name__ == '__main__':
    p1 = Process(target=task, args=('大张红',))
    p1.daemon = True
    p1.start()
    time.sleep(1)
    print('恕瑞玛皇帝:小吴勇嗝屁了')

僵尸进程与孤儿进程

  1. 僵尸进程
    进程执行完毕后并不会立刻销毁所有的数据 会有一些信息断站保留下来
    比如进程号、进程执行时间、进程消耗功率等给父进程查看
    所有的进程都会变成僵尸进程
  2. 孤儿进程
    子进程正常运行 父进程意外死亡 操作系统针对孤儿进程会派遣福利院管理

多进程数据错乱问题

加进程锁,变成串行

from multiprocessing import Process, RLock
import json
import time
import random


def check_num(name):
    with open(r'data.json', 'r', encoding='utf8') as f:
        data_dict = json.load(f)
        print(f'{name}车票剩余:', data_dict.get('ticket_num'))


def pay_num(name):
    with open(r'data.json', 'r', encoding='utf8') as f:
        data_dict = json.load(f)
        time.sleep(random.randint(1, 3))
        if data_dict.get('ticket_num') > 0:
            data_dict['ticket_num'] -= 1

            with open(r'data.json', 'w', encoding='utf8') as f:
                json.dump(data_dict, f, ensure_ascii=False)
                print(f'恭喜您{name}抢到了')
        else:
            print('没抢到')


def run(name, lock):
    check_num(name)
    with lock:
        pay_num(name)


if __name__ == '__main__':
    lock = RLock()
    for i in range(10):
        p = Process(target=run, args=(str(i), lock))
        p.start()

小问题

1.将TCP服务端使用多进程实现并发效果
import socket
from multiprocessing import Process

server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
server.bind(('127.0.0.1', 8889))
server.listen(5)


def task(conn):
    while True:
        print(conn.recv(1024).decode('utf8'))
        conn.sendall(b'hahahahahaahahah')


if __name__ == '__main__':
    while True:
        conn, addr = server.accept()
        print(addr)
        p = Process(target=task, args=(conn,))
        p.start()

标签:__,p1,name,Process,编程,print,并发,进程
From: https://www.cnblogs.com/clever-cat/p/16904831.html

相关文章

  • 并发编程
    内容概要并发编程理论与操作系统发展史多道技术近程理论及调度算法内容概要同步与异步阻塞与非阻塞创建进程的两种方式进程join方法进程间数据隔......
  • 网络编程与并发
    今日内容同步与异步用来表达任务的提交方式同步 提交完任务之后原地等待人物的返回结果期间不做任何事异步 提交完任务之后不原地等待任务的返回结果直接去做其......
  • 进入python的世界_day34_网络编程——同步与异步、进程、消息队列、互斥锁
    一、同步与异步、阻塞与非阻塞1.同步与异步介绍​ 一种方式,可以用来表示提交任务方提交任务后的行为同步:好比去办车牌的时候,提交了资料就呆在大厅一动不动,等着审核结果......
  • 08.大促高并发系统下JVM如何调优指导(4)
                                                         ......
  • 网络并发1
    今日内容详细同步与异步用来表达任务的提交方式同步 提交完任务之后原地等待任务的返回结果期间不做任何事异步 提交完任务之后不原地等待任务的返回结果直接去做......
  • 并发编程1
    今日内容概要同步与异步阻塞与非阻塞创建进程的多种方式进程间的数据隔离进程的join方法IPC机制生产者与消费者模型进程对象的多种方法守护进程僵尸进程与孤儿......
  • Pthread 并发编程(三)——深入理解线程取消机制
    Pthread并发编程(三)——深入理解线程取消机制基本介绍线程取消机制是pthread给我们提供的一种用于取消线程执行的一种机制,这种机制是在线程内部实现的,仅仅能够在共享内......
  • 可编程 USB 转串口适配器
    概述可编程USB转UART/I2C/SMBus/SPI/CAN/1-Wire适配器USB2S(USBToSerialports)是多种数字接口物理层协议转发器,自带强大灵活的S2S协议固件程序,支持嵌入C语言程序开发,可实现......
  • Java并发中锁的种类
    锁的分类Java中锁分为以下几种:乐观锁、悲观锁共享锁、独享锁公平锁、非公平锁互斥锁、读写锁可重入、不可重入锁synchronized锁升级(无锁->偏向锁->轻量级锁......
  • Unix/Linux编程(MySQL数据库系统)
    1MySQL介绍MySQL是一个关系数据库系统在关系数据库中,数据存储在表中。每个表由多个行和列组成。表中的数据相互关联。表也可能与其他表有关联。关系结构使得可在表上运行......