并发与串行

并发编程

并发与串行

程序默认执行方式是串行,即自上而下,当前任务执行完毕才能执行下一个任务,比较浪费时间

问题举例:

​ 从硬盘读取大文件

​ 执行input

学习并发的目的

编写可执行多个任务的程序,提高效率

串行和并发都是程序处理任务的方式

如何实现并发

多进程 (核心原理:多到技术)

多线程

协程

进程和程序

程序是 一堆代码放在一个文件中 通常后缀为exe 原本是存储在硬盘上的

进程是 将代码从硬盘读取到内存然后执行 产生的

进程是由程序产生的

一个程序可以产生多个进程,例如qq多开 每一个进程都具备一个PID 进程变编号 且是唯一的

多道技术

空间复用

时间复用 (切换+保存)

​ 切换的时机:遇到IO或执行时间超出阈值

一个进程的三种操作

阻塞

非阻塞

运行

并发重要概念

串行:自上而下顺序执行

并发:同时执行多个任务,但本质是在不同进程间切换,由于速度非常快,所以感觉是同时运行

并行:是真正的同时运行,但需要具备多核CPU,几核CPU就能并行几个任务,当任务数量超过核心数还是并发执行

三个概念都是用于描述处理任务的方式

阻塞:指程序遇到了IO操作,无法执行代码的 一种状态

​ input默认是一个阻塞操作

非阻塞:指的是程序没有遇到IO操作的一种状态

我们可以用一些手段非阻塞的操作变成非阻塞的操作,例如非阻塞的socket

PID和PPID

PID 是当前进程的编号

PPID 是父进程的编号

注意:当我们运行py文件时其实运行的是python解释器

访问PID与PPID

import os
os.getpid()
os.getppid()

join的使用

from multiprocessing import Process
import time
import random


def task(n):
    time.sleep(random.randint(1, 3))
    print('-------->%s' % n)


if __name__ == '__main__':
    ps = []
    for i in range(1, 4):
        p = Process(target=task, args=(i,))
        p.start()
        ps.append(p)

    for i in ps:
        i.join()

    print('-------->4')
from multiprocessing import Process
import time
import random

def task(n):
    time.sleep(random.randint(1,3))
    print('-------->%s' %n)

if __name__ == '__main__':
    p1=Process(target=task,args=(1,))
    p2=Process(target=task,args=(2,))
    p3=Process(target=task,args=(3,))

    p1.start()
    p1.join()
    p2.start()
    p2.join()
    p3.start()
    p3.join()
    print('-------->4')

进程对象常用属性

if __name__ == '__main__':
    p = Process(target=task,name="老司机进程")
    p.start()
    # p.join()
    # print(p.name)
    # p.daemon #守护进程
    # p.join()
    # print(p.exitcode) # 获取进程的退出码   就是exit()函数中传入的值
    # print(p.is_alive())  # 查看进程是否存活
    # print("zi",p.pid) # 获取进程id
    # print(os.getpid())
    # p.terminate()  #终止进程  与strat 相同的是 不会立即终止,因为操作系统有很多事情要做  
    # print(p.is_alive())

僵尸进程与孤儿进程

孤儿进程 当父进程已经结束 而子进程还在运行 子进程就称为孤儿进程 尤其存在的必要性,没有不良影响

僵尸进程 当一个进程已经结束了但是,它仍然还有一些数据存在 此时称之为僵尸进程

在linux中,有这么一个机制,父进程无论什么时候都可以获取到子进程的的 一些数据

子进程 任务执行完毕后,确实结束了但是仍然保留一些数据 目的是为了让父进程能够获取这些信息

linux中 可以调用waitpid来是彻底清除子进程的残留信息

python中 已经封装了处理僵尸进程的操作 ,无需关心

原文地址:https://www.cnblogs.com/einsam/p/11123202.html