浅谈对进程的理解

一、多任务的概念

1、举个栗子

思考:我们在使用网盘下载资料的时候,为什么要多个任务同时下载呢?

答:多个任务同时执行可以大大提高程序的执行效率

2、提出问题

问题:利用我们目前所学的技术,我们能否实现多任务操作呢?

答:不能,因为之前所写的程序都是单任务的,也就是说一个函数或者方法执行完成 , 另外一个函数或者方法才能执行。要想实现多个任务同时执行就需要使用多任务。多任务的最大好处是充分利用CPU资源,提高程序的执行效率。

3、什么是多任务

多任务是指在同一时间内执行多个任务。

例如: 现在电脑安装的操作系统都是多任务操作系统,可以同时运行着多个软件。

4、多任务的两种表现形式

① 并发

② 并行

5、并发操作

并发:在一段时间内交替去执行多个任务。

例如:对于单核cpu处理多任务,操作系统轮流让各个任务交替执行,假如:软件1执行0.01秒,切换到软件2,软件2执行0.01秒,再切换到软件3,执行0.01秒……这样反复执行下去, 实际上每个软件都是交替执行的 . 但是,由于CPU的执行速度实在是太快了,表面上我们感觉就像这些软件都在同时执行一样 . 这里需要注意单核cpu是并发的执行多任务的。

6、并行操作

并行:在一段时间内真正的同时一起执行多个任务。

对于多核cpu处理多任务,操作系统会给cpu的每个内核安排一个执行的任务,多个内核是真正的一起同时执行多个任务。这里需要注意多核cpu是并行的执行多任务,始终有多个任务一起执行。

二、进程的概念

1、程序中实现多任务的方式

在Python中,想要实现多任务可以使用==多进程==来完成。

2、进程的概念

进程(Process)是资源分配的最小单位,它是操作系统进行资源分配和调度运行的基本单位,通俗理解:一个正在运行的程序就是一个进程。

例如:正在运行的qq , 微信等 他们都是一个进程。

注: 一个程序运行后至少有一个进程

3、多进程的作用

☆ 未使用多进程

思考:

​ 图中是一个非常简单的程序 , 一旦运行hello.py这个程序 , 按照代码的执行顺序 , func_a函数执行完毕后才能执行func_b函数 . 如果可以让func_a和func_b同时运行 , 显然执行hello.py这个程序的效率会大大提升 .

☆ 使用了多进程

三、多进程完成多任务

1、多进程完成多任务

① 导入进程包
import multiprocessing
​
② 通过进程类创建进程对象 
进程对象 = multiprocessing.Process() 
​
③ 启动进程执行任务
进程对象.start()

2、通过进程类创建进程对象

进程对象 = multiprocessing.Process([group [, target=任务名 [, name]]])

参数说明:

参数名说明
target执行的目标任务名,这里指的是函数名(方法名)
name进程名,一般不用设置
group进程组,目前只能使用None

3、进程创建与启动的代码

边听音乐边敲代码:

import multiprocessing
import time
​
​
def music():
    for i in range(3):
        print('听音乐...')
        time.sleep(0.2)
​
​
def coding():
    for i in range(3):
        print('敲代码...')
        time.sleep(0.2)
​
if __name__ == '__main__':
    music_process = multiprocessing.Process(target=music)
    coding_process = multiprocessing.Process(target=coding)
​
    music_process.start()
    coding_process.start()

4、进程执行带有参数的任务

Process([group [, target [, name [, args [, kwargs]]]]])

参数说明:

参数名说明
args以元组的方式给执行任务传参,args表示调用对象的位置参数元组,args=(1,2,'anne',)
kwargs以字典方式给执行任务传参,kwargs表示调用对象的字典,kwargs={'name':'anne','age':18}

案例:args参数和kwargs参数的使用

import multiprocessing
import time
​
​
def music(num):
    for i in range(num):
        print('听音乐...')
        time.sleep(0.2)
​
​
def coding(count):
    for i in range(count):
        print('敲代码...')
        time.sleep(0.2)
​
​
music_process = multiprocessing.Process(target=music, args=(3, ))
coding_process = multiprocessing.Process(target=coding, kwargs={'count': 3})
​
music_process.start()
coding_process.start()

案例:多个参数传递

import multiprocessing
import time
​
​
def music(num, name):
    for i in range(num):
        print(name)
        print('听音乐...')
        time.sleep(0.2)
​
​
def coding(count):
    for i in range(count):
        print('敲代码...')
        time.sleep(0.2)
​
​
if __name__ == '__main__':
    music_process = multiprocessing.Process(target=music, args=(3, '多任务开始'))
    coding_process = multiprocessing.Process(target=coding, kwargs={'count': 3})
​
    music_process.start()
    coding_process.start()

四、获取进程编号

1、进程编号的作用

当程序中进程的数量越来越多时 , 如果没有办法区分主进程和子进程还有不同的子进程 , 那么就无法进行有效的进程管理 , 为了方便管理实际上每个进程都是有自己编号的。

2、两种进程编号

① 获取当前进程编号

getpid()

② 获取当前进程的父进程ppid = parent pid

getppid()

3、获取当前进程编号

import os
​
​
def work():
    # 获取当前进程的编号
    print('work进程编号', os.getpid())
    # 获取父进程的编号
    print('work父进程的编号', os.getppid())
    
​
work()

案例:获取子进程编号

import multiprocessing
import time
import os
​
​
def music(num):
    print('music>> %d' % os.getpid())
    for i in range(num):
        print('听音乐...')
        time.sleep(0.2)
​
​
def coding(count):
    print('coding>> %d' % os.getpid())
    for i in range(count):
        print('敲代码...')
        time.sleep(0.2)
​
​
if __name__ == '__main__':
    music_process = multiprocessing.Process(target=music, args=(3, ))
    coding_process = multiprocessing.Process(target=coding, kwargs={'count': 3})
​
    music_process.start()
    coding_process.start()

案例:获取父进程与子进程编号

import multiprocessing
import time
import os
​
​
def music(num):
    print('music>> %d' % os.getpid())
    print('music主进程>> %d' % os.getppid())
    for i in range(num):
        print('听音乐...')
        time.sleep(0.2)
​
​
def coding(count):
    print('coding>> %d' % os.getpid())
    print('music主进程>> %d' % os.getppid())
    for i in range(count):
        print('敲代码...')
        time.sleep(0.2)
​
​
if __name__ == '__main__':
    print('主进程>> %d' % os.getpid())
    music_process = multiprocessing.Process(target=music, args=(3, ))
    coding_process = multiprocessing.Process(target=coding, kwargs={'count': 3})
​
    music_process.start()
    coding_process.start()

五、进程应用注意点

1、进程间不共享全局变量

实际上==创建一个子进程就是把主进程的资源进行拷贝产生了一个新的进程==,这里的主进程和子进程是互相独立的。

案例:

import multiprocessing
​
my_list = []
​
​
def write_data():
    for i in range(3):
        my_list.append(i)
        print('add:', i)
    print(my_list)
​
​
def read_data():
    print('read_data', my_list)
​
​
if __name__ == '__main__':
    # 创建写入数据进程
    write_process = multiprocessing.Process(target=write_data)
    # 创建读取数据进程
    read_process = multiprocessing.Process(target=read_data)
​
    # 启动进程执行相关任务
    write_process.start()
    time.sleep(1)
    read_process.start()

原理分析:

三个进程分别操作的都是自己进程里面的全局变量my_list, 不会对其它进程里面的全局变量产生影响,所以进程之间不共享全局变量,只不过进程之间的全局变量名字相同而已,但是操作的不是同一个进程里面的全局变量。

知识点小结:

创建子进程会对主进程资源进行拷贝,也就是说子进程是主进程的一个副本,好比是一对双胞胎,之所以进程之间不共享全局变量,是因为操作的不是同一个进程里面的全局变量,只不过不同进程里面的全局变量名字相同而已。

2、主进程与子进程的结束顺序

代码演示:

import multiprocessing
import time
​
​
# 工作函数
def work():
    for i in range(10):
        print('工作中...')
        time.sleep(0.2)
​
​
if __name__ == '__main__':
    # 创建子进程
    work_process = multiprocessing.Process(target=work)
    # 启动子进程
    work_process.start()
​
    # 延迟1s
    time.sleep(1)
    print('主进程执行完毕')

执行结果:

☆ 解决方案一:设置守护进程

import multiprocessing
import time
​
​
# 工作函数
def work():
    for i in range(10):
        print('工作中...')
        time.sleep(0.2)
​
​
if __name__ == '__main__':
    # 创建子进程
    work_process = multiprocessing.Process(target=work)
    # 设置守护主进程,主进程退出后子进程直接销毁,不再执行子进程中的代码
    work_process.daemon = True
    # 启动子进程
    work_process.start()
​
    # 延迟1s
    time.sleep(1)
    print('主进程执行完毕')

☆ 解决方案二:销毁子进程

import multiprocessing
import time
​
​
# 工作函数
def work():
    for i in range(10):
        print('工作中...')
        time.sleep(0.2)
​
​
if __name__ == '__main__':
    # 创建子进程
    work_process = multiprocessing.Process(target=work)
    # 启动子进程
    work_process.start()
​
    # 延迟1s
    time.sleep(1)
    
    # 让子进程直接销毁,表示终止执行, 主进程退出之前,把所有的子进程直接销毁就可以了
    work_process.terminate()
    
    print('主进程执行完毕')

提示: 以上两种方式都能保证主进程退出子进程销毁

  • 26
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值