一、操作系统基础:

进程的概念起源于操作系统,操作系统其它所有概念都是围绕进程来的,所以我们了解进程之前先来了解一下操作系统

操作系统位于计算机硬件与应用软件之间,本质也是一个软件。操作系统由操作系统的内核(运行于内核态,管理硬件资源)以及系统调用(运行于用户态,为应用程序员写的应用程序提供系统调用接口)两部分组成

两大功能:

  1.将复杂的硬件操作封装成简单的接口给应用程序或者用户去使用

  2.将多个进程对硬件的竞争变得有序

操作系统处理进程的发展简略:

  1.串行:一个任务完整的运行完毕才运行下一个任务

  2.并发:多个任务看起来是同时运行的

  3.多道技术(复用-->共享)

    (1)空间上的复用:多个任务复用内存空间

    (2)时间上的复用:多个任务复用cpu的时间

      时间上的复用又分为两种:

  1. 一个任务占用时间过长会被操作系统剥夺走cpu的执行权限:比起串行执行反而降低效率
  2. 一个任务遇到IO操作也会被操作系统剥夺走cpu的执行权限:比起串行执行可以提升效率 

二、进程

程序仅仅是一堆代码而已,而进程指的是程序运行的过程

(一)、进程的创建

开启进程的方式1:(直接使用Process)

from multiprocessing import Process
import time def task(name):
print('%s is running'%name)
time.sleep(3)
print('%s is done'%name) #在windows系统上,开启子进程的操作必须放到 if __name__ == '__main__':中,避免递归 if __name__ == '__main__':
p = Process(target=task,args=('egon',))
# Process(target=task,kwargs={'name':'egon'})
p.start()#只是向操作系统发送了一个开启子进程的信号
print('主')

开启进程的方式2:(继承Process来自定义类,重写run方法)

from multiprocessing import Process
import time class Myprocess(Process):
def __init__(self,name):
super().__init__()
self.name = name
def run(self):
print('%s is running' % self.name)
time.sleep(3)
print('%s is done' % self.name) if __name__ == '__main__':
p = Myprocess('egon')
p.start()
print('主')

结果都为:


egon is running
egon is done

注:run:如果在创建Process对象的时候不指定target,那么就会默认执行Process的run方法:

(二)、join方法

join阻塞当前进程,直到调用join方法的那个进程执行完,再继续执行当前进程

from multiprocessing import Process
import time def task(name,n):
print('%s is running'%name)
time.sleep(n)
print('%s is done'%name) if __name__ == '__main__': start = time.time()
p_j =[]
for i in range(1,4):
p = Process(target=task,args=('egon',i))
p.start()
p_j.append(p) for i in p_j:
i.join()
print(time.time() - start)
print('主')

当不加join方法时,主进程先运行完毕,加了join就会等子进程运行完毕后才运行主进程,先依次调用start启动进程,再依次调用join要求主进程等待子进程的结束。

为什么要先依次调用start再调用join,而不是start完了就调用join

from multiprocessing import Process
import time def task(name,n):
print('%s is running'%name)
time.sleep(n)
print('%s is done'%name) if __name__ == '__main__':
p1 = Process(target=task,args=('egon',1))
p2 = Process(target=task,args=('alex',2))
start = time.time()
p1.start()
p1.join()
p2.start()
p2.join()
print(time.time() - start)
print('主')

程序变成了串行执行,并不是并发了。

(三)进程直接的内存空间互相隔离

from multiprocessing import Process
import time n=100
def task():
global n
n=0 if __name__ == '__main__':
p = Process(target=task)
p.start()
p.join()
print(n)#

主进程与子进程之间互不干扰,子进程是对主进程的拷贝。

(四)、进程对象其他相关属性或方法

进程pid(每一个进程在操作系统内都有一个唯一的id号)

使用multiprocessing内的current_process

from multiprocessing import Process,current_process
import time def task():
print('%s is running'%current_process().pid)
time.sleep(3)
print('%s is done'%current_process().pid) if __name__ == '__main__':
p = Process(target=task)
p.start()
print('主 %s'%current_process().pid)

使用os模块下的getpid方法

from multiprocessing import Process,current_process
import time,os def task():
print('%s is running'%os.getpid())
time.sleep(3)
print('%s is done'%os.getpid()) if __name__ == '__main__':
p = Process(target=task)
p.start()
print('主 %s'%os.getpid())

getppid()获取进程的主进程id号

from multiprocessing import Process,current_process
import time,os def task():
print('%s is running 爹是:%s' %(os.getpid(),os.getppid()))
time.sleep(30)
print('%s is done 爹是:%s' %(os.getpid(),os.getppid())) if __name__ == '__main__':
p=Process(target=task)
p.start()
print('主:%s 主他爹:%s' %(os.getpid(),os.getppid()))

from multiprocessing import Process,current_process
import time,os def task():
print('%s is running'%os.getpid())
time.sleep(3)
print('%s is done'%os.getpid()) if __name__ == '__main__':
p = Process(target=task,name='子进程1')
p.start()
print(p.name)#查看进程名
# p.terminate()杀死子进程
print(p.is_alive())#查看子进程是否存活
print('主 %s'%os.getpid())

(五)、僵尸进程与孤儿进程

僵尸进程:子进程的结束和父进程的运行是一个异步过程,即父进程永远无法预测子进程 到底什么时候结束。在 unix 或 linux 的系统中,当一个子进程退出后,它就会变成一个僵尸进程,如果父进程没有通过 wait 或者waitpid()系统调用来读取这个子进程的退出状态的话,这个子进程就会一直维持僵尸进程状态。

僵尸进程的危害:如果进程不调用wait / waitpid的话, 那么保留的那段信息就不会释放,其进程号就会一直被占用,但是系统所能使用的进程号是有限的,如果大量的产生僵死进程,将因为没有可用的进程号而导致系统不能产生新的进程. 此即为僵尸进程的危害,应当避免。

孤儿进程:如果一个子进程的父进程先于子进程结束,则该子进程将变成孤儿进程。它将由init进程收养,称为init进程的子进程。init就是孤儿院

清除僵尸进程:方法1,结束父进程(主进程),当父进程退出的时候,僵尸进程也会被清除

       方法2,在处理程序中调用 wait 系统调用来清除僵尸进程

(六)、守护进程

守护进程本质就是一个“子进程”,该“子进程”的什么周期小于等于被守护进程的生命周期

p.daemon = True#放在start前面
from multiprocessing import Process
import time def task(name):
print('太监 %s活着。。。'%name)
time.sleep(3)
print('太监 %s死了。。。'%name) if __name__ == '__main__':
p = Process(target=task,args=('lxx',))
p.daemon = True#放在start前面
p.start() print('egon 正在死...')

(七)、互斥锁

每个进程互相独立,相互之间没有任何关系,某个进程要更改共享数据时,先将其锁定,此时资源的状态为“锁定”,其他线程不能更改;直到该线程释放资源,将资源的状态变成“非锁定”,其他的线程才能再次锁定该资源。互斥锁保证了每次只有一个线程进行写入操作,从而保证了多线程情况下数据的正确性。

import json
import time,random
from multiprocessing import Process,Lock def search(name):
with open('db.json','rt',encoding='utf-8') as f:
dic=json.load(f)
time.sleep(1)
print('%s 查看到余票为 %s' %(name,dic['count'])) def get(name):
with open('db.json','rt',encoding='utf-8') as f:
dic=json.load(f)
if dic['count'] > 0:
dic['count'] -= 1
time.sleep(random.randint(1,3))
with open('db.json','wt',encoding='utf-8') as f:
json.dump(dic,f)
print('%s 购票成功' %name)
else:
print('%s 查看到没有票了' %name) def task(name,mutex):
search(name) #并发
mutex.acquire()
get(name) #串行
mutex.release() # with mutex:
# get(name) if __name__ == '__main__':
mutex = Lock()
for i in range(10):
p=Process(target=task,args=('路人%s' %i,mutex))
p.start()
# p.join() # join只能将进程的任务整体变成串行

python-并发编程之多进程的更多相关文章

  1. Python并发编程__多进程

    Python并发编程_多进程 multiprocessing模块介绍 python中的多线程无法利用多核优势,如果想要充分地使用多核CPU的资源(os.cpu_count()查看),在python中大 ...

  2. Python进阶(4)_进程与线程 (python并发编程之多进程)

    一.python并发编程之多进程 1.1 multiprocessing模块介绍 由于GIL的存在,python中的多线程其实并不是真正的多线程,如果想要充分地使用多核CPU的资源,在python中大 ...

  3. python并发编程02 /多进程、进程的创建、进程PID、join方法、进程对象属性、守护进程

    python并发编程02 /多进程.进程的创建.进程PID.join方法.进程对象属性.守护进程 目录 python并发编程02 /多进程.进程的创建.进程PID.join方法.进程对象属性.守护进程 ...

  4. python并发编程之多进程(三):共享数据&进程池

    一,共享数据 展望未来,基于消息传递的并发编程是大势所趋 即便是使用线程,推荐做法也是将程序设计为大量独立的线程集合 通过消息队列交换数据.这样极大地减少了对使用锁定和其他同步手段的需求, 还可以扩展 ...

  5. python并发编程之多进程(二):互斥锁(同步锁)&进程其他属性&进程间通信(queue)&生产者消费者模型

    一,互斥锁,同步锁 进程之间数据不共享,但是共享同一套文件系统,所以访问同一个文件,或同一个打印终端,是没有问题的, 竞争带来的结果就是错乱,如何控制,就是加锁处理 part1:多个进程共享同一打印终 ...

  6. 28 python 并发编程之多进程

    一 multiprocessing模块介绍 python中的多线程无法利用多核优势,如果想要充分地使用多核CPU的资源(os.cpu_count()查看),在python中大部分情况需要使用多进程.P ...

  7. 二 python并发编程之多进程-重点

    一 multiprocessing模块介绍 python中的多线程无法利用多核优势,如果想要充分地使用多核CPU的资源(os.cpu_count()查看),在python中大部分情况需要使用多进程.P ...

  8. 二 python并发编程之多进程实现

    一 multiprocessing模块介绍 二 process类的介绍 三 process类的使用 四 守护进程 五 进程同步(锁) 六 队列 七 管道 八 共享数据 九 信号量 十 事件 十一 进程 ...

  9. python并发编程之多进程(实践篇)

    一 multiprocessing模块介绍 python中的多线程无法利用多核优势,如果想要充分地使用多核CPU的资源,在python中大部分情况需要使用多进程.Python提供了multiproce ...

  10. 第十篇.2、python并发编程之多进程

    一 multiprocessing模块介绍 python中的多线程无法利用多核优势,如果想要充分地使用多核CPU的资源(os.cpu_count()查看),在python中大部分情况需要使用多进程.P ...

随机推荐

  1. 四十一、Linux 线程——线程同步之条件变量

    41.1 概念 41.1.1 条件变量的介绍 互斥锁的缺点是它只有两种状态:锁定和非锁定 条件变量通过允许线程阻塞和等待另一个线程发送信号的方法弥补了互斥锁的不足 条件变量内部是一个等待队列,放置等待 ...

  2. 二十五、Linux 进程与信号---exec函数

    25.1 介绍 在用 fork 函数创建子进程后,子进程往往要调用一种 exec 函数以执行另一个程序 当进程调用一种 exec 函数时,该进程完全由新程序代换,替换原有进程的正文,而新程序则从其 m ...

  3. 【演变】Ajax(AjAj)到WebSocket

    提出问题:A  =>  服务器  =>  B           B端浏览器如何知道服务器有A发来的数据? 解决方案: 第1种:频繁轮询    间隔1秒B向服务器讨要数据,就算数据为空.[ ...

  4. (一)python的前世今生

    一:Python介绍 python的创始人为吉多·范罗苏姆(Guido van Rossum)(目前还活着),诞生于1989年,是一个脚本解释程序,由于python语言结构优美,清晰简单,随着人工智能 ...

  5. 关于利用PHP访问MySql数据库的逻辑操作以及增删改查实例操作

    PHP访问MySql数据库 <?php //造连接对象$db = new MySQLi("localhost","root","",& ...

  6. A - 签到题

    给定一个长度为N的数组A=[A1, A2, ... AN],已知其中每个元素Ai的值都只可能是1, 2或者3. 请求出有多少下标三元组(i, j, k)满足1 ≤ i < j < k ≤ ...

  7. zookeeper.KeeperException$UnimplementedException: KeeperErrorCode = Unimplemented for {root.path}

    1 异常结果 org.apache.zookeeper.KeeperException$UnimplementedException: KeeperErrorCode = Unimplemented ...

  8. Spark思维导图之Shuffle

  9. java中的绝对路径和相对路径

    1.基本概念的理解 绝对路径:绝对路径就是你的主页上的文件或目录在硬盘上真正的路径,(URL和物理路径)例如:C:/xyz/test.txt 代表了test.txt文件的绝对路径.http://www ...

  10. python(十一)面向切面编程AOP和装饰器

    二.装饰器 装饰器可以在给函数修改功能的同时并不改变这个函数本身.(以下用的都是python2.7) 首先,在python里面函数是对象,在下面的函数里"fun"是函数也是对象可以 ...