python 多任务---进程

文章目录

  • 一、 什么是进程
  • 二 、进程与程序的区别
  • 三、线程与进程的区别
  • 四、python中进程的创建
  • 五、多进程完成多任务
  • 六 、进程的传参与不共享全局变量

一、 什么是进程

进程:正在进行的一个过程或者说一个任务。而负责执行任务的则是cpu。

进程由三部分组成:
代码段,数据段,PCB(进程控制块)
进程的三个基本状态:
就绪状态:获得了除CPU之外运行需要的所有资源
执行状态:获得了所有资源,处于正在执行的状态
阻塞状态:因为各种原因,导致进程放弃了cpu,导致进程无法继续执行,此时进程处于内存

二 、进程与程序的区别

程序仅仅只是一堆代码而已,而进程指的是程序的运行过程。 也可以说一个程序运行起来后,代码+用到的资源就可称之为进程,它是操作系统分配资源的基本单元。

三、线程与进程的区别

1. 一个程序至少有一个进程,一个进程至少有一个线程;
2. 线程的划分尺度小于进程,使得多线程程序的并发性高;
3. 进程在执行过程中拥有独立的内存单元,而多个线程共享内存,从而极大地提高了程序的运行效率;
4. 每个独立的线程有一个程序运行的入口、顺序执行序列和程序的出口。但是线程不能够独立执行,必须依存在应用程序中,由应用程序提供多个线程执行控制;
5. 从逻辑角度来看,多线程的意义在于一个应用程序中,有多个执行部分可以同时执行。但操作系统并没有将多个线程看作多个独立的应用,来实现进程的调度和管理以及资源分配。

线程和进程在使用上各有优缺点:线程执行开销小,但不利于资源的管理和保护;而进程则相反。

四、python中进程的创建

可以说进程的创建和线程很相似,线程中使用threading模块里面的Thread类创建出实例对象, 然后通过start()方法真正的去产生一个新的线程。而进程则使用multiprocessing模块,这是一个跨平台版本的多进程模块,提供了一个Process类来代表一个进程对象,这个对象可以理解为是一个独立的进程,可以执行另外的事情,然后也是通过start()方法真正的去产生一个新的进程。
备用知识点:

查看当前进程:
	import os		
	os.getpid()

	查看当前进程父进程:
	import os
	os.getppid()

开启子进程的方式:
         1 p = Process(target=func,args=(,))
           target: 是子进程要执行的任务
           args:是父进程给子进程传递的参数
         2 自定义类,去继承Process

      进程的方法:
          p.start()开启子进程,底层调用的是p.run()


 进程的常用方法:
      (1) start()  开启一个子进程
      (2) join()   异步变同步(就是让父进程停留在join这句话,等待子进程执行结束,父进程再继续执行)
      (3) is_alive() 判断进程是否活着
      (4) terminate()   杀死进程


进程的常用属性
       (1) p.name =    给p进程一个名字
       (2) p.pid       返回p进程的pid
       (3) p.daemon = True   将p进程设置为守护进程。(True为守护进程,False为普通进程)


           守护进程的两个特点:
              守护进程会随着父进程的结束而结束
              守护进程不能再创建子进程(不能要孩子)

五、多进程完成多任务

不仅可以通过线程完成多任务,进程也是可以的,与线程协程比较,进程可以说是最稳定的,但是比较吃cpu。下面举个多进程完成多任务的例子:

import multiprocessing
import time
# 通过一个进程号去判断
import os
# 多进程完成多任务
def sing():
    for i in range(1,4):
        print("我正在唱第%s首歌" % i)
        # 查看当前进程的父进程
        print("进程在sing中运行, 进程号pid为:%s,父进程为%s" % (os.getpid(),os.getppid())) # 获取当前进程号
        time.sleep(1.5)

def dance():
    for i in range(1,4):
        print("我正在跳第%s支舞" % i)       
        print("进程在dance中运行, 进程号pid为:%s,父进程为%s" % (os.getpid(),os.getppid())) # 获取当前进程号

        time.sleep(1.5)

def main():
    print("进程在main中运行, 进程号pid为:", os.getpid()) # 获取当前进程号   
    p1 = multiprocessing.Process(target = sing)
    p2 = multiprocessing.Process(target = dance)
    p1.start()
    p2.start()
    time.sleep(5)
    print("进程在main中运行, 进程号pid为:", os.getpid()) # 获取当前进程号
   


if __name__ == '__main__':
    main()

程序执行结果:
python 多任务---进程_第1张图片

六 、进程的传参与不共享全局变量

和线程传参基本一样,程序示例:

import multiprocessing

def demo1(*args,**kwargs):
    print(args)
    print(kwargs)

def main():
    p1 = multiprocessing.Process(target=demo1,args=(1,2,3),kwargs={'a':1,"b":2})
    p1.start()

if __name__ == '__main__':
    main()

执行结果:
python 多任务---进程_第2张图片

证实进程不共享全局变量:

import multiprocessing
import time

list1 = [1,2,3]

def demo1():
    list1.append(4) 
    print("在demo1中,list1的值是:",str(list1))

def demo2():
    list1.append(5) 
    print("在demo2中,list1的值是:",str(list1))

def main():
    p1 = multiprocessing.Process(target=demo1)
    p2 = multiprocessing.Process(target=demo2)
    p1.start()
    # time.sleep(1)
    # join,和sleep一样,达到进程等待阻塞的效果,但是由于进程所占用的资源比较庞大,
    # 我们并不确定p1具体需要多长时间才能执行完,所以sleep的时间无法确定,
    # 相应的join方法就应运而生了,这个不需要具体的时间就能达到进程等待阻塞的效果
    p1.join() # 还可以传参,比如p1.join(5) 设置超时等待,超过5秒释放资源程序继续往下执行

    p2.start()

if __name__ == '__main__':
    main()
    time.sleep(3)
    list1.append(6) 
    print("在主进程中,list1的值是:",str(list1))

程序执行结果:
python 多任务---进程_第3张图片
理论上如果进程共享全局变量,在demo1中会有list1 = [1,2,3,4],在demo2中会有list1 = [1,2,3,4,5],在主进程中会有list1 = [1,2,3,4,5,6],然而我可以清楚的看到执行结果并不像我们预料的那样,实际上它的每一个进程对全局变量的操作互不干扰,所以可以证实进程是不共享全局变量的。

你可能感兴趣的:(网络编程,进程,进程与线程的区别,进程完成多任务,证实进程不共享全局变量)