Day 31 并发编程
目录
- 并发编程
- 并发和串行
- 学习并发的目的
- 进程是什么
- 操作系统是什么
- 操作系统发展史
- 第二代计算使用的是批处理系统,存在以下三个问题
- 第三代计算机
- 第四代计算机
- 多道技术
- 并发编程中的重要概念
- python如何使用多进程
- 1. 导入multiprocessing中的Process类 实例化这个类 指定要执行的任务target
- 2. 导入multiprocessing中的Process类 继承这个类 覆盖run方法 将要执行的任务放入run中开启进程是会自动执行该函数
- 进程之间内存相互隔离
- join函数
- 进程对象的常用属性
- 僵尸进程和孤儿进程
并发编程
并发和串行
- 程序默认的执行方式是串行,即程序自上而下一行一行执行,必须把当前任务执行完毕才能执行下一个任务
学习并发的目的
就是编写可以同时执行多个任务的程序,从而提高效率
串行和并发都是程序处理任务的方式
## 实现并发的方式
- 多进程
- 多线程
- 协程
进程是什么
进程是指正在运行的程序,是操作系统调度以及进行资源分配的基本单位
当程序从硬盘读取到内存中运行的时候进程就产生了
多进程:指的是同一时间有多个程序被装入内存并执行
多进程的实现原理其实就是操作系统调度进程的原理
操作系统是什么
操作系统就是一款特殊的软件
操作系统和普通软件的区别:
- 操作系统可以直接与硬件交互
- 操作系统是受保护的,不能直接被修改
- 操作系统更加长寿,一旦完成基本不会修改,如系统内核
操作系统的主要功能
- 隐藏了硬件复杂的操作,提供了简单的api接口
- 将硬件的资源竞争变得有序可控
GUI图形化用户界面
操作系统发展史
掌握多道技术的实现原理,就是多进程的实现原理
第二代计算使用的是批处理系统,存在以下三个问题
- 需要人为参与
- 任务串行执行
- 程序员调试效率低
第三代计算机
使用SPOOLING联机计数
- 多道技术
多终端多用户
第四代计算机
大规模集成电路+多用户多终端
特点:具备GUI图形化界面,普通人也可以使用
多道技术
实现原理:
空间复用
同一时间加载多个任务到内存中,多个进程之间的内存区域需要相互隔离,这种隔离是物理隔离,为了保证数据安全性
时间复用
操作系统会在多个进程之间做切换
切换进程的两种情况:
1.但给一个进程遇到IO操作时会自动切换
2.当任务执行时间过长(超时)强制切换
切换进程前需要记录当前进程的状态,同时频繁的切换也消耗系统资源
当所有任务没有IO操作时,切换执行反而降低了效率,但是为了保证并发执行必须要牺牲效率
多道技术总结:切换+保存
有了多道技术,计算机就可以同时并发处理多个任务
并发编程中的重要概念
串行:从上到下依次执行
并发:多个任务同时执行,本质是多个进行不断在切换,由于切换速度快,所以感觉是同时运行
并行:真正意义上的同时运行,有几个核心就能并行几个任务,如果超过核心数就使用并发执行
以上三个都是用于描述处理任务的方式
一个进程的三种状态
阻塞:当程序遇到IO操作,无法继续执行代码时的一种状态
非阻塞 :程序没有遇到IO操作的状态,正常运行
就绪:程序等待CPU运行
阻塞非阻塞也可以用来描述执行任务的方式
三种状态的互相切换
程序正常运行,当运行时间超过阈值,会进入就绪状态,等待cpu执行完其他的进程后,恢复到运行状态继续执行
当程序遇到IO操作,会进入阻塞状态,当结束阻塞状态后,程序会进入就绪状态,等待cpu空闲后继续执行本程序
野指针和僵尸指针
野指针:内存中的地址被删除
僵尸指针:内存中的地址因为某种原因没有被清除
进程的创建和销毁
创建:
- 用户交互式请求
- 有一个正在运行的程序调用了开启进程的接口
- 一个批处理作业开始
- 系统初始化
销毁:
- 任务完成
- 强制结束 windows:taskkill/linux:kill
- 程序异常
进程和程序
程序是一堆代码存放在文件中
进程就是程序中的代码从硬盘读入内存后产生的
进程是由程序产生的
一个程序可以产生多个进程,每一个进程都有一个唯一的PID
进程的层次结构
在linux中进程具备父子关系,是一个树状结构,可以相互查找到对方
在windows中,没有层级关系,父进程可转让子进程的句柄
父进程与子进程:例如qq打开了浏览器,qq就是父进程,浏览器就是子进程
PID和PPID
PID是当前进程的编号
PPID是当前程序的父进程的编号
我们运行py文件的时候其实是运行python解释器,所以运行py文件的父进程就是python解释器
import os
os.getpid()
os.getppid()
python如何使用多进程
1. 导入multiprocessing中的Process类 实例化这个类 指定要执行的任务target
import os
from multiprocessing import Processdef task():print("this is sub process")print(f"sub process id {os.getpid()}" )if __name__ == '__main__':p = Process(target=task)p.start() print("this is parent process")print(f"parent process is: {os.getpid()}")print("over")
linux和windows开启进程的方式区别
linux会将父进程的内存数完整复制一份给子进程
windows会导入父进程的代码,从新执行一遍,来获取需要处理的任务,所以在编写代码时如果是windows,需要把开启进程的代码放在main判断中
2. 导入multiprocessing中的Process类 继承这个类 覆盖run方法 将要执行的任务放入run中开启进程是会自动执行该函数
from multiprocessing import Process
import osclass Downloader(Process):def __init__(self,url,size,name):super().__init__()self.url = urlself.size = sizeself.name = namedef run(self):print(os.getpid())passif __name__ == '__main__':m = Downloader()m.start()print("parent over",os.getpid())
进程之间内存相互隔离
from multiprocessing import Process
import os,timea = 257def task():global aprint("2",a,id(a))a = 200if __name__ == '__main__':p = Process(target=task)p.start() time.sleep(4)print(a)
join函数
就是让主进程等待子进程运行完再执行
from multiprocessing import Process
import timedef task1(name):for i in range(10000):print(f'{name} run')def task2(name):for i in range(100):print(f'{name} run')if __name__ == '__main__': p1 = Process(target=task1,args=("p1",))# args 是给子进程传递的参数 必须是元组p1.start() p2 = Process(target=task2,args=("p2",))p2.start() p2.join() p1.join()print("over")
进程对象的常用属性
if __name__ == '__main__':p = Process(target=task,name="老司机进程")p.start()# p.join()# print(p.name)# p.daemon #守护进程# p.join()# print(p.exitcode) # 获取进程的退出码 就是exit()函数中传入的值# print(p.is_alive()) # 查看进程是否存活# print("zi",p.pid) # 获取进程id# print(os.getpid())# p.terminate() #终止进程 与strat 相同的是 不会立即终止,因为操作系统有很多事情要做 # print(p.is_alive())
僵尸进程和孤儿进程
孤儿进程:当父进程已经结束,而子进程还在运行,子进程就成为孤儿进程,孤儿进程有其存在的意义,没有不良影响,孤儿进程会被操作系统接管
僵尸进程:当一个进程已经结束了,但是他仍然还有一些数据存在,此时称之为僵尸进程
在linux中,有这么一个机制,父进程无论什么时候都可以获取到子进程的一些数据;子进程任务执行完毕后,确实结束了但是仍然保留了一些数据,目的是为了让父进程能够获取这些信息;linux中,可以调用waitpid来彻底清除子进程的残留信息
python中已经封装了处理僵尸进程的操作
转载于:https://www.cnblogs.com/masterjian924/p/11124038.html
Day 31 并发编程相关推荐
- Java并发编程学习 + 原理分析(建议收藏)
总结不易,如果对你有帮助,请点赞关注支持一下 微信搜索程序dunk,关注公众号,获取博客源码 Doug Lea是一个无私的人,他深知分享知识和分享苹果是不一样的,苹果会越分越少,而自己的知识并不会因为 ...
- Java并发编程71道面试题及答案
Java并发编程71道面试题及答案 1.在java中守护线程和本地线程区别? java中的线程分为两种:守护线程(Daemon)和用户线程(User). 任何线程都可以设置为守护线程和用户线程,通过方 ...
- Java并发编程有多难?这几个核心技术你掌握了吗?
本文主要内容索引 1.Java线程 2.线程模型 3.Java线程池 4.Future(各种Future) 5.Fork/Join框架 6.volatile 7.CAS(原子操作) 8.AQS(并发同 ...
- Java并发编程73道面试题及答案——稳了
点击上方"方志朋",选择"置顶或者星标" 你的关注意义重大! 1.在java中守护线程和本地线程区别? java中的线程分为两种:守护线程(Daemon)和用户 ...
- java(9)并发编程
整理自<java 并发编程的艺术> 1. 上下文切换 即使是单核处理器也支持多线程执行代码,CPU通过给每个线程分配CPU时间片来实现这个机制.时间片是CPU分配给各个线程的时间,因为时间 ...
- Java并发编程,无锁CAS与Unsafe类及其并发包Atomic
为什么80%的码农都做不了架构师?>>> 我们曾经详谈过有锁并发的典型代表synchronized关键字,通过该关键字可以控制并发执行过程中有且只有一个线程可以访问共享资源,其 ...
- Java并发编程71道面试题及答案 1
1.在java中守护线程和本地线程区别? java中的线程分为两种:守护线程(Daemon)和用户线程(User). 任何线程都可以设置为守护线程和用户线程,通过方法Thread.setDaemon( ...
- Java并发编程:CopyOnWrite容器的实现
Java并发编程:并发容器之CopyOnWriteArrayList(转载) 原文链接: http://ifeve.com/java-copy-on-write/ Copy-On-Write简称COW ...
- 【Java 并发编程】线程池机制 ( ThreadPoolExecutor 线程池构造参数分析 | 核心线程数 | 最大线程数 | 非核心线程存活时间 | 任务阻塞队列 )
文章目录 前言 一.ThreadPoolExecutor 构造参数 二.newCachedThreadPool 参数分析 三.newFixedThreadPool 参数分析 四.newSingleTh ...
最新文章
- Visual Studio 2008 Samples Page
- hashcode()方法和equals()方法
- opencv学 之图像傅里叶变换dft
- github果然强大
- (日常搬砖)voc(xml)格式的标注转换为coco(json)格式
- .Net 并发写入文件的多种方式
- 列表显示数据 但是数据的字体颜色要js添加
- 一份无锡工程师的分享
- BUPT-CSAPP 2019 Fall 3.58 3.60 3.63
- 华芯投资40亿现金收购美芯片测试设备厂商Xcerra
- 正和岛青年徽商正和塾小组2021年首聚—走进掌榕
- axios发送请求,后端报错:所需的防伪表单字段“__RequestVerificationToken”不存在
- Java规则引擎Drools急速入门
- 【小沐学C++】C++17实现文件操作<filesystem>
- 数据仓库(六)---分布式SQL查询引擎---presto介绍
- php安装和环境配置
- 概率论与数理统计_陈希儒版_第一章:事件的概率
- 【ArcGIS】空间数据库的迁移
- 将jpg文件转换成bgr二进制文件
- 会画画的计算机学霸,国际班超牛学霸 琴棋书画全能的计算机高手