并发编程

总结:

并发编程是多任务同时发生

并行编程 是多任务同时进行

进程是指程序在运行时产生一系列的过程,依赖操作系统

多道技术是指让多个程序可以不去抢CPU资源有2种方法,空间复用和时间复用,空间复用:指操作系统把内存分几个块将程序放入,同一时间可以存在多个程序,时间复用:利用程序IO的等待CPU就可以切换打开其它程序

阻塞和非阻塞,阻塞指程序运行时进入到IO,或sleep,非阻塞是指程序正常运行

进程和程序,一个程序是可以有多个进程

进程也有父子关系,怎么区别用os.getpid()子进程,os.getppid()父进程来取得ID

进程的三种状态:就绪态,运行态,阻塞态

python中开启子进程的2种方式:1.直接用process,2.class继承关系(具体下面查看)

进程内存相互隔离验证

join函数 用于将子程结果定在start之后

 

 

 

 

 

***什么是并发编程

1.并发编程 就是让一个程序中多个任务可以同时被处理

***什么是进程

进程是正在运行的程序一系列过程的统称,也是操作系统在调度和进行资源分配的基本单位

进程有三种状态:就绪态,运行态,阻塞态

进程是实现并发的一种方式

没有操作系统就没有进程

下图是操作系统在整个计算机中所在的位置:

 

***什么是多道技术?

多道是指多个程序,为了解决多个程序竞争或共享同一个资源CPU的有序调度问题

操作系统采用多道技术后,可以控制进程的切换,或者进程之间去争抢CPU执行权限

解决办法

空间上的复用:

将内存分割几个部份,每部份放入一个程序,同一时间在内存有多个程序

 

 

(空间上的复用问题:

1.程序之间内存必须分割,分割需要在硬件层实现,由操作系统控制。若不切割,1个程序可以访问另一个程序, 失去安全性。例QQ就会可以访问操作系统内存,意味着qq程序能拿到操作系统所有权

2. 其次失去稳定性,当程序崩溃有可以把别的程序内存也回收,比方把操作系统 内存给回收,操作系统崩贵)

 

 

时间上的复用:

当一个程序在等待IO操作,另一个程序可以使用CPU

当一个进程占用CPU时间过长也会切换到下个程序

PS:计算任务不适用多道技术,因为计算任务是不需要等待的。

***进程与程序

进程是正在运行的程序,当一堆代码被系统加载到内存中并执行时,就有了进程

例 看菜谱----做菜   (菜谱就是程序,做菜是进程。看着菜谱正在做菜)

注意!一个程序可以产生多个进程,就像可以打开多个QQ运行

 

***如何区别进程

1.系统会给每个进程分配一个进程编号即PID,如同人需要一个身份证号来区分

import os
print(os.getpid()) #子进程ID
#20956

 

验证:tasklist 用于查看所有进程消息 tasklist | findstr py, 、taskkill/f/pid  用于结束指定进程【在CMD命令操作】

 

2.当一个进程a开启了另一个进程b时,a称为b的父进程,b为a的子进程

import os
print('self',os.getpid()) #子进程
print('parent',os.getppid()) #父进程 指当下的pycharm程序
self 5516
parent 9200

 

***并发与并行( 这些情况的发生取决于操作系统)

并发:多个事件同时发生,例如洗衣服和做饭,同时发生在程序的世界2个任务在切换,给人的感觉是同时进行,也被称为伪并行

并行:多个事件同时进行 ,一个人是无法真正并执行任务,在计算机中单核CPU无法真正并行。

***阻塞与非阻塞(指的是程序的状态)

阻塞状态是因为程序遇到了IO操作(输入输出),或是sleep,导致后续的代码不能被CPU执行,非阻塞与之相反,表示程序正在正常被cpu执行

进程有三种状态:就绪态,运行态,阻塞态

代码操作实现并发******

一个进程就是一个任务,CPU会从上到下依次执行代码,

python中开启子进程的两种方式

 

1.实例化Process   单词解释:multiprocessing 多重处理, process过程, target=目标

from multiprocessing import Process   ---因为导入是个内置类,所以P要大写
import time
def task(name):
  print('%s is running'%name) ————————子进程
  # time.sleep(1) -------------模拟进程的执行过程
  pri模拟是先走子程还是走这个
  print('%s is done'%name)------------------子进程
if __name__ == '__main__':
#在windows系统之上,开启子进程的操作一定要放到下面
  p=Process(target=task,args=('jack',))-----父进程的程序,把需要的参数写入
  p.start()         -#向操作系统发送请求,操作系统会申请内存空间,然后把父进程 的数据拷贝给子进程,作为子进程的初始状态

  print(11111111) ----------模拟是先走子程还是走这个
   
p=Process(target=task,args=('jack',),kwargs=()) args输入是元祖类型,kwargs输入是字典类型
11111111
jack is running
jack is done

继承Process类 并覆盖run方法

 

class Myclass(Process):    ----建一个类
  def __init__(self,url):---------为process增加一个url,但不全部替换
      super().__init__()
      self.url = url

  def run(self):   ------------固定用法
      print('%s 下载文件'%self.url)
      print('家家')
if __name__ == '__main__':

  p=Myclass('www.baidu.com')
  p.start()
   

 

进程内存相互隔离验证

from multiprocessing import Process

import time
x=199
y=100
def task():
  global x   --------全局X
  x=0
  print('一只鸟死啦',x)
if __name__ == '__main__':
  # print(x)
  p=Process(target=task)
  p.start()
  # time.sleep(2)  
  # print(y)
  ----------------------------
   
    199
一只鸟死啦 0
100

   
  1.正常执行将先执行if下面的所有输出,再执行def对象
  2.若进和睡眠,会先执行if 的X,再跳def里面再跳 if的y
  3.因为内存是互相隔离,所有global全局也无法改变,各自的ID地址和值
 
   
   

join函数

调用start后的操作都由操作系统控制,何时开启,何时执行如何执行,应用程序无法操作,join函数就是可以让父进程等待子进程结束后继续执行

from multiprocessing import process
x=100
y=80
z=12

def tack():
  x=9
  print('一只鸟死了%s'%x)

if __name__ == '__main__':
  print(y)
  p=Process(target=tack)
  p.start()
  p.join()------#在启动之后加入,会先运行if下第一个,然后再def里面
  print(z)
   
  80
一只鸟死了9
12

 

案例二

from multiprocessing import process
import time
def task(n):
  print('%s is run'%n)
  time.sleep(n)
if __name__ == '__main__':
  p=Process(target=task,args=(1,))
  p1=Process(target=task,args=(2,))
  p2=Process(target=task,args=(3,))
  p.start()
  p1.start()
  p2.start()
  p2.join()

  p.join()
  p1.join()

  start_time = time.time()
  print('y ',time.time()-start_time)


  p_l=[]
  for i in range(1,4):
      p=Process(target=task,args=(i,))
      p_l.append(p)
      p.start()
  for p in p_l:
      p.join()
      print('ye',time.time()-start_time)

Process对象常用属性

import time

from multiprocessing import process
def task(n):
  print('%s is run'%n)
  time.sleep(n)
if __name__ == '__main__':
  p=Process(target=task,args=(1,),name='任务1')
  p.start()
  print(p.pid)---------子进程ID
  print(p.name) -----------子进程名字
  p.join()--------------------优先输出子进程
  print(p.is_alive()) ----------判断子进程是否存活,若已结束程序就是False
  print('yo')
  18004
任务1
1 is run
False
yo

 

孤儿进程与僵尸进程(了解)

孤儿进程 :父程已经终止,但是子进程还在运行是无害的

僵尸进程 是父进程抛弃它,指子进程执行完成所有任务,已经终止了但还残留一些信息,以为父程 会来找它(进程id 进程名),但是父进程没有去处理这些残留信息,导致残留信息占用系统内存

当出现大量的僵尸进程时会占用系统资源,可以把它父进程杀掉,僵尸就成了孤儿,操作系统会负责回收数据

(僵尸是死了也不找不到它)

 

怎么杀 :taskkill

tasklist|findstr python

posted @ 2018-12-28 19:13  陈大哥的小可爱  阅读(156)  评论(0)    收藏  举报