慢就是快15-1 多进程 多线程

并发与并行

1.并发:

概念:在一段时间内,当cPu面对多个任务时,会将每个任务交替着执行一段时间。

特点:

(1).对于某个瞬间,cPU实际上只在执行一个任务。

(2).cPu通过高频切换不同的任务,让每个任务都能得到推进,仿佛多个任务在"同时执行"。

2.并行

概念:并行依赖于多个cPu,或多核心的cPu,在同一时刻,每个核心都在执行不同的任务。

特点:

(1).对于某个瞬间,每个cPu(或每个核心)都在执行不同的任务。

(2).通过多个CPU(或多个核心)同时工作的方式,让多个任务真的在同时执行。

说明:在现代操作系统中,并发与并行通常都是同时存在的。

同步与异步

1.同步(sync):

概念:发起一个任务之后,需要等该任务完成后,才能继续执行后续任务。

表现:当前执行流会被『阻塞』。

2.异步(async):

概念:发起一个任务之后,不必等该任务完成,就可以继续执行其他任务。备注:虽然不必等待任务完成,但任务完成后,仍然可以通过特定方式获取结果。

表现:当前执行流不会被『阻塞』。

三、注意区分概念:

并发/并行:描述的是任务如何被执行,即:多个任务在执行时,cPU要如何处理。

同步/异步:描述的是任务如何被组织和等待,即:要不要等当前发起的任务执行完,再进行下一个任务。

A注意点:CPU的核心数和执行速度,不会改变任务之间的逻辑依赖关系!

例如:一旦任务1、任务2、任务3之间被设计为同步关系,那么:即便CPU切换任务的速度再快,核心数量再多,也不会在[任务1】没完成的情况下去启动【任务2】

进程与线程

1.进程:

(1).一个正在运行的程序或软件,背后就对应着一个或多个进程。

(2).进程是操作系统进行资源分配的基本单位。

(3).每个进程都有自己独立的一块内存空间。

2.线程:

(1).线程是进程内部的执行单元(一个进程中可以有多个线程)

(2).线程是操作系统进行CPU调度的基本单位。

(3).同一进程内的线程共享进程资源。

主进程 子进程

python 复制代码
import os
print(os.getpid()) #当前进程的pid
print(os.getppid()) #当前进程的父进程pid

在windows操作系统中,查看:进程名、父进程pid、进程pid的命令如下:

wm1c process get Name,ParentProcessId,ProcessId

使用 Process 创建进程

python 复制代码
import os
import time
from multiprocessing import Process
#定义一个speak函数,功能是:每隔一秒说话一次(一共说话1e次)
def speak():
    for index in range(10):
        print(f'我在说话{index},进程pid是:{os.getpid()}')
        time.sleep(1)

#定义一个study函数,功能是:每隔一秒学习一次(一共学习15次)
def study():
    for index in range(15):
        print(f'我在学习{index},进程pid是:{os.getpid()}')
        time.sleep(1)

# speak()
# study()
# 注意:一定要写if __name__=='__main__'这个判断,原因如下:
#   1.当创建子进程时,Python并不会把父进程内存里的speak 函数直接交给子进程。
#   2.Python会启动一个全新的Python解释器进程,重新执行当前的 .py 文件(作为模块)
#   3.在执行过程中,重新定义出一个speak函数,交给子进程。
if __name__ == '__main__':
    #创建两个Process类的实例对象(进程对象),分别是p1和p2。
    # 注意点1:p1和p2 就对应着以后的两个子进程,在创建它们的时候,就要指定好他们要执行的任务。
    # 注意点2:此时的p1和p2只是代码层面的两个进程对象,操作系统还没有真的创建p1和p2两个进程。
    p1 = Process(target=speak)
    p2 = Process(target=study)

    #调用进程对象的start方法,会立刻向操作系统申请一个进程,并且会将该进程交由操作系统进行调度
    p1.start()
    p2.start()

Process参数

python 复制代码
import os
import time
from multiprocessing import Process, current_process
#定义一个speak函数,功能是:每隔一秒说话一次(一共说话1e次)
def speak(a,b,msg):
    for index in range(10):
        print(f'{msg}--{a}--{b}--{current_process().name}--我在说话{index},进程pid是:{os.getpid()}')
        time.sleep(1)

#定义一个study函数,功能是:每隔一秒学习一次(一共学习15次)
def study():
    for index in range(15):
        print(f'我在学习{index},进程pid是:{os.getpid()}')
        time.sleep(1)

if __name__ == '__main__':
    # Process的参数:
    # group: 默认值为None(应当始终为None)
    # target: 子进程要执行的可调用对象,默认值为None。
    # name: 进程名称,默认为None,如果设置为None,Python会自动分配名字。
    # args: 给target传的位置参数(元组)
    # kwargs: 给target传的关键字参数(字典)
    # daemon:标记进程是否为守护进程,取值为布尔值(默认为None,表示从创建方进程继承)
    p1 = Process(target=speak,name='说话进程',args=(666,888),kwargs={'msg':'haha'})
    p2 = Process(target=study)

    p1.start()
    p2.start()

锁(Lock)

python 复制代码
import os
import time
from multiprocessing import Process, Lock,RLock

def speak(lock):
    for index in range(10):
        # 上锁: 如果锁是空闲的,立刻上锁,继续往下执行;如果锁被别人拿着: 当前进程会阻塞等待(原地等)
        lock.acquire()
        print(f'我在说话{index}')
        # 释放锁: acquire和release必须成对出现,否则会永远卡住(死等)
        lock.release()
        time.sleep(1)

#定义一个study函数,功能是:每隔一秒学习一次(一共学习15次)
def study(lock):
    for index in range(15):
        # with lock:会自动完成两件事:
        # (1).进入前: 自动执行lock.acquire()上锁
        # (2).离开后: 自动执行lock.release()释放锁
        # 好处:即便代码块里发生异常,也能保证释放锁,避免"卡死"
        # 备注:RLock可以多次上锁
        with lock:
            print(f'我在学习{index},进程pid是:{os.getpid()}')
        time.sleep(1)

if __name__ == '__main__':
    # lock=Lock()
    lock=RLock()
    p1 = Process(target=speak, args=(lock,))
    p2 = Process(target=study, args=(lock,))

    p1.start()
    p2.start()

join方法 | terminate方法

join方法的作用:阻塞当前进程,等 join前面的进程执行完,再继续往下执行。

join(timeout),其中 timeout 是可选参数,表示等多久,单位是秒。

python 复制代码
import os
import time
from multiprocessing import Process, Lock,RLock

def speak():
    for index in range(10):
        print(f'我在说话{index}')
        time.sleep(1)

def study():
    for index in range(15):
        print(f'我在学习{index},进程pid是:{os.getpid()}')
        time.sleep(1)

if __name__ == '__main__':
    p1 = Process(target=speak)
    p2 = Process(target=study)
    p1.start()
    p2.start()

    p1.join()#让主进程等 p1进程执行完毕后,主进程再继续执行。
    p1.join()#让主进程等 p2进程执行完毕后,主进程再继续执行。

    time.sleep(3)
    p1.terminate() #强制终止

进程守护

复制代码
什么是守护进程?
  1.一种“依附于主进程存在的子进程”,一旦主进程结束,它就会被自动终止。
  2.简言之:主进程一死,守护进程必跟着死。
守护进程的使用场景:
  1.后台监控类任务
  2.日志/统计/采样类任务
  3.辅助型“陪跑任务”

#注意点:

1.守护进程必须是 子进程。

2.主进程结束,守护进程也会随之结束。

3.守护进程中,不允许再创建新的子进程。

4.必须在start 之前,start()之后,不能再设置daemon

python 复制代码
import os
import time
from multiprocessing import Process

def monitor():
    while True:
        try:
            with open('log.txt','r',encoding='utf-8') as file:
                lines=sum(1 for _ in file)
        except FileExistsError:
            lines=0
        print(f'我是守护进程{os.getpid()},log.txt共有{lines}行')
        time.sleep(1)


if __name__ =='__main__':
    print(f'我是主进程({os.getpid()})中的[第一行]代码')
    p1=Process(target=monitor,daemon=True)
    p1.start()
    #向文件中写入数据
    with open('log.txt', 'a',encoding='utf-8') as file1:
        for index in range(10):
            file1.write(f'尚硅谷{index}\n')
            file1.flush()
            time.sleep(1)
    print('我是最后一行代码')

进程之间不共享变量

进程之间不共享内存,因此也不共享任何变量

相关推荐
WenGyyyL1 小时前
从零理解强化学习:为什么 AI 需要 Advantage,而不只是 Reward?
人工智能·python·深度学习·机器学习·nlp
pan_junbiao1 小时前
Go语言中的空白标识符
开发语言·后端·golang
卡卡~~1 小时前
C++学习
开发语言·c++
qetfw1 小时前
Bash 基础:脚本执行、引号与命令替换验证
linux·开发语言·chrome·bash
杜 硕2 小时前
从零开始的C++生活——第四讲
开发语言·c++·生活
云和数据.ChenGuang2 小时前
Python 集合(set)常用函数详解与实战案例
开发语言·python·深度学习·langchain
梯度下降者2 小时前
python在哪些方面有应用,python可以用在哪些方面
人工智能·python·web开发·科学计算·应用领域
隔窗听雨眠2 小时前
从PHP2Shell回望:PHP内核漏洞的二十年演进与AI时代的攻防转折
开发语言·人工智能·php
lisw052 小时前
分岔论揭示演化突变密码
开发语言·算法·数学建模