进程(process)
在面向线程设计的系统(如当代多数操作系统、Linux 2.6及更新的版本)中,进程本身不是基本运行单位,而是线程的容器。进程拥有自己独立的内存空间,所属线程可以访问进程的空间。程序本身只是指令、数据及其组织形式的描述,进程才是程序的真正运行实例。 例如,我们在PyCharm开发环境中写好一个程序,运行的时候python解释器完成解释并执行该程序。
进程 = 程序段 + 数据段 + PCB
全局解释器锁GIL
GIL是计算机程序设计语言解释器用于同步线程的一种机制,它使得任何时刻仅有一个线程在执行。即便在多核心处理器上,使用 GIL 的解释器也只允许同一时间执行一个线程。Python的Cpython解释器(普遍使用的解释器)使用GIL,在一个Python解释器进程内可以执行多线程程序,但每次一个线程执行时就会获得全局解释器锁,使得别的线程只能等待,由于GIL几乎释放的同时就会被原线程马上获得,那些等待线程可能刚唤醒,所以经常造成线程不平衡享受CPU资源,此时多线程的效率比单线程还要低下。可以说它的初衷是很好的,为了保证线程间的数据安全性;但是随着时代的发展,GIL却成为了python并行计算的最大障碍,但这个时候GIL已经遍布CPython的各个角落,修改它的工作量太大,特别是对这种开源性的语音来说。但幸好GIL只锁了线程,我们可以再新建解释器进程来实现并行,那这就是multiprocessing的工作了。
开启子进程的两种方式
第一种:直接调用
from multiprocessing import Process
import time
def task(name):
print(f\'{name}is running \')
time.sleep(3)
print(f\'{name} is done\')
if __name__ == \'__main__\':
# windows操作系统开启多进程,必须得写在main下面。
p = Process(target=task,args=(\'路一\',)) # args 一定是一个元组的形式
p.start()
print(\'===主进程\')
# start与print几乎是同时发出,但是由于操作系统调用子进程会慢一些。#
# 整个py文件是主进程
# p.start通知操作系统,你给我在内存中开辟一个空间,将p进程放进去,让cpu执行。
第二种 :继承式调用
from multiprocessing import Process
import time
class Myprocess(Process):
def __init__(self,name):
# 这里的顺序是有要求,不然反过来写会覆盖。
super().__init__() # 必须要执行父类的init
self.name = name
def run(self): # 必须定义这个名字
print(f\'{self.name}is running \')
time.sleep(3)
print(f\'{self.name} is done\')
if __name__ == \'__main__\':
p = Myprocess(\'路一\')
p.start()
print(\'主进程\')
获取进程以及父进程的pid
操作系统如何区分进程?每个进程都有一个唯一标识,pid
1.在终端查看进程的pid,cmd中输入tasklist
2.在终端查看指定的进程pid,cmd中输入 tasklist | findstr pycharm