8.9 day30 并发编程 进程理论 进程方法 守护进程 互斥锁
多道技术
1.空间上的复用
多个程序共用一套计算机硬件
多道技术原理

2.时间上的复用
切换+保存状态
1.当一个程序遇到IO操作 操作系统会剥夺该程序的CPU执行权限( 提高了CPU的利用率,并且也`不影响程序的执行效率` )
2.当一个程序长时间占用CPU 操作系统也会剥夺该程序的CPU执行权限( `降低了程序的执行效率` )
并发: 看起来像同时运行就可以
并行: 真正意义上的同时运行
单核的计算机不能实现并行,但是可以实现并发
进程
程序和进程的区别
程序: 一段代码
进程: 正在进行的程序 进程相互独立
进程调度
要想多个进程交替运行,操作系统必须对这些进程进行调度,这个掉浮是遵循一定法则的,这就是进程的调度算法
先来先服务 (最简单的调度算法,有利于长作业,不利于短作业)
短作业优先算法(短作业优先,对短作业有利,对长作业不利)
时间片轮转法+多级反馈队列
时间片: 就好比将一秒等分成N多份如果一个程序他需要更多的时间片,这个程序的执行优先级就会下降,比如A程序在运行,此时用户点击了B程序,那操作系统就会立刻停止A程序的执行,保存A程序的运行进度,然后去响应B程序

大概就这些?
进程三态状态转换图

在了解其他概念之前,我们首先要了解进程的几个状态。在程序运行的过程中,由于被操作系统的调度算法控制,程序会进入几个状态:就绪,运行和阻塞。
(1)就绪(Ready)状态
当进程已分配到除CPU以外的所有必要的资源,只要获得处理机便可立即执行,这时的进程状态称为就绪状态。
(2)执行/运行(Running)状态当进程已获得处理机,其程序正在处理机上执行,此时的进程状态称为执行状态。
(3)阻塞(Blocked)状态正在执行的进程,由于等待某个事件发生而无法执行时,便放弃处理机而处于阻塞状态。
引起进程阻塞的事件可有多种,
例如,等待I/O完成、申请缓冲区不能满足、等待信件(信号)
input
print
文件操作
sleep
...其他的
结束阻塞态
input获取到值
print输出完结果
文件读取完毕
睡眠结束。
时间片的时间到了(占用CPU太久了)会自动进入就绪态,而不是阻塞,等待下一次CPU执行
写程序的理想状态: 尽量少的进入阻塞态

同步异步
表示的是任务的提交方式
同步:任务提交以后,原地等待的任务的执行并拿到返回结果才走,期间不做任何事(程序界面的表现就是
异步:任务提交以后,不再原地等待,而是继续执行下一行代码(结果是要的 但是用其他方式获取)
import time
def test()
time.sleep()
res = test()
print('hello')
阻塞非阻塞
表示的是程序的运行状态
阻塞: 对应进程三状态中的阻塞态
非阻塞: 对应进程三状态中的就绪态、运行态
异步非阻塞形式效率最高
创建进程的两种方式
创建进程就是在内存中重新开辟一块内存空间
将运行产生的代码丢进去
一个进程对应在内存就是一块独立的内存空间
进程与进程之间数据是隔离的,无法直接交互,可以通过某些技术实现间接交互
这两种必须敲出来
from multiprocessing
...
def test(name):
print('%s is running' %name)
time.sleep(3)
print('%s is over' %name)
"""
Windows 创建进程会将代码以模块的方式从上往下执行一遍
Linux 会直接将代码完完整整的拷贝一份(fork一份)
windows创建进程一定要在 if __name__ == '__main__': 代码块内创建 否则报错
"""
if __name__ == '__main__':
p = Process(target = test,args = ('margo',)) # 创建一个进程对象
p.start() # 告诉操作系统帮你创建一个进程
print('主') # 为什么先打印’主‘
#因为创建p.start()这个进程的时间远远大于执行接下来语句的时间
"""
创建进程就是在内存中重新开辟一块内存空间
将允许产生的代码丢进去
一个进程对应在内训就是一块独立的内存空间
进程与进程之间数据是隔离的 无法直接交互
( 可以通过某些技术间接进行交互 )
只要开一个进程 就是重新申请一块内存空间
零散知识点
join方法
from multiprocessing import Process
from multiprocessing import Process
def test(name):
print('%s is running'% name)
time.sleep(3)
print('%s is over'% name)
p = Prosess(target = test,args = ('margo',))
p.start()
print('主')
# 这样会报错 要把三行 放在main里面
if __name__ == '__main__':
p = Prosess(target = test,args = ('margo',))
p.start()
# 主进程代码等待子进程运行结束 才继续进行
print('主')
# 用join
if __name__ == '__main__':
p = Prosess(target = test,args = ('margo',))
p.start()
# 主进程代码等待子进程运行结束 才继续进行
p.join()
print('主')
if __name__ == '__main__':
p = Prosess(target = test,args = ('margo',))
p1 = Prosess(target = test,args = ('margo',))
p2 = Prosess(target = test,args = ('margo',))
p.start() # 仅仅是告诉操作系统帮你创建一个进程
p1.start() # 创建进程的顺序是随机的
p2.start() # 至于这个进程什么时候创,操作系统随机决定
# 主进程代码等待子进程运行结束 才继续进行
p.join()
print('主')
if __name__ == '__main__':
for i in range(3):
p = Process(target = )
p = Prosess(target = test,args = ('margo',))
p1 = Prosess(target = test,args = ('margo',))
p2 = Prosess(target = test,args = ('margo',))
p.start() # 仅仅是告诉操作系统帮你创建一个进程
p1.start() # 创建进程的顺序是随机的
p2.start() # 至于这个进程什么时候创,操作系统随机决定
# 主进程代码等待子进程运行结束 才继续进行
p.join()
print('主')
06 进程间数据是隔离的
money = 100
07 进程对象及其他方法
查看 主主进程
getpid getppid
杀死进程
terminate 杀死当前进程 其实是告诉操作系统
time.sleep(0.1)
p.is_alive()
僵尸进程与孤儿进程
父进程回收子进程资源的两种方式:
1.join方法
2.父进程正常死亡
所有的进程都会步入僵尸进程
孤儿进程
子进程没死 父进程意外死亡
针对Linux会有儿童福利院(init)(只是个名字 别搞混),如果父进程意外死亡,他所创建的子进程都会被福利院收养
守护进程
被守护进程结束后守护进程立刻结束(后面的还未执行的代码直接不执行了)
from multiprocessing import Process
import time
# 古代皇帝死了一般太监都需要陪葬,所以举这么一个例子
def test(name):
print(f'{name}总管正常活着')
time.sleep(3)
print(f'{name}总管正常死亡')
# # windows下创建子进程必须卸载 __main__ 这个结构里
# if __name__ == '__main__':
# p = Process(target=test, args=('margo', ))
# p.start()
# print(f"皇帝bitten寿终正寝")
#
# # 皇帝bitten寿终正寝
# # margo总管正常活着
# # margo总管正常死亡
# # 加上p.daemon = True 让子进程成为守护进程
# if __name__ == '__main__':
# p = Process(target=test, args=('margo', ))
# p.daemon = True # 将该进程设置为守护进程,这一句必须放在start()之前,否则报错
# p.start()
# # 守护进程一般不加 p.join,都等子进程运行完了再接着走主进程那就不是守护进程了
# # p.join() # 加了也能正常运行,但它失去了守护进程的意义
# print(f"皇帝bitten寿终正寝")
#
# # 皇帝bitten寿终正寝
# 加上 time.sleep 给子进程一些运行时间(CPU运行速度超快的,1秒已经很长了)
if __name__ == '__main__':
p = Process(target=test, args=('margo', ))
p.daemon = True
p.start()
time.sleep(0.1) # 暂停0.1 秒,给子进程一点运行时间(子进程和主进程是同步运行的)
# 守护进程一般不加 p.join,都等子进程运行完了再接着走主进程那就不是守护进程了
# p.join() # 加了也能正常运行,但它失去了守护进程的意义
print(f"皇帝bitten寿终正寝")
# margo总管正常活着
# 皇帝bitten寿终正寝
互斥锁
先看一个用并发模拟多人的抢票的案例
import bitten
from multiprocessing import Process
import time
# 查票
def search(i):
with open('07data.txt', 'r', encoding='utf-8') as f:
data = f.read()
ticket_dict = bitten.loads(data)
print(f"用户{i}查询余票为:{ticket_dict.get('ticket')}")
# 买票
def buy(i):
with open('07data.txt', 'r', encoding='utf-8') as f:
data = f.read()
ticket_dict = bitten.loads(data)
time.sleep(3)
if ticket_dict.get('ticket') > 0:
ticket_dict['ticket'] -= 1
print(ticket_dict)
with open('07data.txt', 'wt', encoding='utf-8') as f:
bitten.dump(ticket_dict, f)
print(f"用户{i}抢票成功")
else:
print("没票了!")
def run(i):
search(i)
buy(i)
if __name__ == '__main__':
for i in range(4):
p = Process(target=run, args=(i, ))
p.start()
# {"ticket": 2} 文件数据
# 用户0查询余票为:2
# 用户1查询余票为:2
# 用户2查询余票为:2
# 用户3查询余票为:2
# {'ticket': 1}
# 用户0抢票成功
# {'ticket': 1}
# 用户1抢票成功
# {'ticket': 1}
# 用户2抢票成功
# {'ticket': 1}
# 用户3抢票成功
# 大于余票了(拿到的都是2张票),这样肯定不行
可以看出,文件中虽然只有2张票,这4个用户却都抢票成功了,并且还有一张余票,在现实生活中这种情况肯定是不允许出现的!
当多个进程操作同一份数据时会造成数据的错乱,这个时候必须加锁处理
将并发变成串行,虽然降低了效率,但是提高了数据安全
那么就尝试着用互斥锁来解决这个问题
import json
from multiprocessing import Process, Lock
import time
# 查票
def search(name):
with open('07data.txt', 'r', encoding='utf-8') as f:
data = f.read()
ticket_dict = json.loads(data)
print(f"用户{name}查询余票为:{ticket_dict.get('ticket')}")
# 买票
def buy(name):
with open('07data.txt', 'r', encoding='utf-8') as f:
data = f.read()
ticket_dict = json.loads(data)
time.sleep(1)
if ticket_dict.get('ticket') > 0:
ticket_dict['ticket'] -= 1
print(ticket_dict)
with open('07data.txt', 'wt', encoding='utf-8') as f:
json.dump(ticket_dict, f)
print(f"用户{name}抢票成功")
else:
print("没票了!")
def run(i, mutex):
search(i)
mutex.acquire() # 抢锁,只要有人抢到了锁,其他人必须等待该人释放锁
buy(i)
mutex.release() # 释放锁
if __name__ == '__main__':
mutex = Lock() # 生成了一把锁
for i in range(4):
p = Process(target=run, args=(i, mutex))
p.start()
# {"ticket": 1} 文件数据
# 用户0查询余票为:1
# 用户1查询余票为:1
# 用户2查询余票为:1
# 用户3查询余票为:1
# {'ticket': 0}
# 用户0抢票成功
# 没票了!
# 没票了!
# 没票了!
# 总共1张票,被抢到一张票,票数变为0,符合预期设想
注意
锁不要轻易使用,容易造成死锁现象
只在处理数据的部分加锁,不要再全局加锁(将局部由并发变成串行)
锁必须在主进程中产生(实例化),交给子进程去使用
(在子进程中产生那不就是多把锁了吗)
只要多进程操作同一份数据,就必须要加锁处理
8.9 day30 并发编程 进程理论 进程方法 守护进程 互斥锁的更多相关文章
- 转:【Java并发编程】之七:使用synchronized获取互斥锁的几点说明
转载请注明出处:http://blog.csdn.net/ns_code/article/details/17199201 在并发编程中,多线程同时并发访问的资源叫做临界资源,当多个线程同时访 ...
- 【Java并发编程】之七:使用synchronized获取互斥锁的几点说明
在并发编程中,多线程同时并发访问的资源叫做临界资源,当多个线程同时访问对象并要求操作相同资源时,分割了原子操作就有可能出现数据的不一致或数据不完整的情况,为避免这种情况的发生,我们会采取同步机制,以确 ...
- python并发编程02 /多进程、进程的创建、进程PID、join方法、进程对象属性、守护进程
python并发编程02 /多进程.进程的创建.进程PID.join方法.进程对象属性.守护进程 目录 python并发编程02 /多进程.进程的创建.进程PID.join方法.进程对象属性.守护进程 ...
- Unix网络编程代码 第13章 守护进程和inetd超级服务器
1. 概述 守护进程是在后台运行且不与任何控制终端关联的进程.unix系统通常有很多守护进程在后台运行,执行不同的管理任务. 守护进程没有控制终端通常源于它们由系统初始化脚本启动.然而守护进程也 ...
- Day9 进程理论 开启进程的两种方式 多进程实现并发套接字 join方法 Process对象的其他属性或者方法 守护进程 操作系统介绍
操作系统简介(转自林海峰老师博客介绍) #一 操作系统的作用: 1:隐藏丑陋复杂的硬件接口,提供良好的抽象接口 2:管理.调度进程,并且将多个进程对硬件的竞争变得有序 #二 多道技术: 1.产生背景: ...
- PHP7 网络编程(二)daemon守护进程
前言 在一个多任务的计算机操作系统中,守护进程(英语:daemon,/ˈdiːmən/或/ˈdeɪmən/)是一种在后台执行的计算机程序.此类程序会被以进程的形式初始化.守护进程程序的名称通常以字母“ ...
- Python进阶----线程基础,开启线程的方式(类和函数),线程VS进程,线程的方法,守护线程,详解互斥锁,递归锁,信号量
Python进阶----线程基础,开启线程的方式(类和函数),线程VS进程,线程的方法,守护线程,详解互斥锁,递归锁,信号量 一丶线程的理论知识 什么是线程: 1.线程是一堆指令,是操作系统调度 ...
- [并发编程 - 多线程:信号量、死锁与递归锁、时间Event、定时器Timer、线程队列、GIL锁]
[并发编程 - 多线程:信号量.死锁与递归锁.时间Event.定时器Timer.线程队列.GIL锁] 信号量 信号量Semaphore:管理一个内置的计数器 每当调用acquire()时内置计数器-1 ...
- linux分享一:进程全攻略--守护进程(服务)
概括: 进程是程序的运行实例.进程对应一个唯一的进程PID, 统一程序的多个实例可以同时运行,他们的pid互不相同. 进程一般分为交互进程.批处理进程和守护进程(daemons)三类 一:什么是守护进 ...
- 创建进程,join方法,进程对象相关属性和方法,僵尸进程和孤儿进程,守护进程,互斥锁
创建进程 在python中提供了一个multiprocessing模块可以帮助我们使用多进程解决问题.在multiprocessing 模块中有一个类Process. from multiproces ...
随机推荐
- 用Python玩数据-笔记整理-第二章
条件结构: if语句: if expression: #比较/成员/逻辑运算符 expr_true_suite #代码块必须缩进4个空格 else语句: if expression: expr_tru ...
- 学习4:总结# 1.列表 # 2.元祖 # 3.range
列表 -- list 有序,可变的,索引, 作用:存储数据的,支持很多种数据类型 定义方式: lst = [1,"alex","黑哥"] 增: append 追 ...
- 个人永久性免费-Excel催化剂功能第29波-追加中国特色的中文相关自定义函数
中文世界里,有那么几个需求在原生Excel里没提供,例如财务部的数字转大写金额,文字转拼音等,在其他插件里,大部分是以功能区菜单按钮的方式提供.Excel催化剂认为,最佳的使用方式乃是自定义函数的方式 ...
- Shrio多Realm认证及认证策略
在大型的系统中,安全数据可能会存放在多个数据库中,而且每个数据的加密方式也是不一样的,那么单一的Realm就无法完成. 这时,就需要用到多Realm认证了,多Realm又涉及到认证策略,及在多个Rea ...
- 洛谷 P1101-题解
这道题可以用深搜(回溯)来写,相信大部分人都是这么想的,但是有些人可能在一些地方饶了半天,所以这里就贴一下我的思路,个人觉得自己的很好懂,除了tx和ty那里,但是tx和ty的那种用法对于输出路径的题目 ...
- MapRedue详细工作流程
MapRedue详细工作流程 简述 (1)客户端submit之前获取待处理的数据信息,根据参数配置,形成一个任务分配的规划. (2)提交切片信息到YARN(split.xml,job.split,wc ...
- fjnuoj 1003 学长的QQ号
题目: //QQ是一个9位数,由1,2,3,4,5,9组成,且第1.6位数字相同,第2.4位数字相同,第5.7位数字相同. //我的QQ就在符合上诉条件中的所有9位数从小到大排第 ...
- Python文件的两种用途
目录 一.Python文件的两种用途 一.Python文件的两种用途 python文件总共有两种用途,一种是执行文件:另一种是被当做模块导入. 编写好的一个python文件可以有两种用途: 脚本,一个 ...
- 【Arduino】66种传感器模块系列实验(2)---光敏电阻模块
实验二:光敏电阻传感器模块我手里这块是三针版的,挺秀气吧 光敏电阻是用硫化隔或硒化隔等半导体材料制成的特殊电阻器,其工作原理是基于内光电效应.光照愈强,阻值就愈低,随着光照强度的升高,电阻值迅速降低, ...
- linux初学者-磁盘拉伸缩减篇
linux初学者-磁盘拉伸缩减篇 在系统的使用过程中,往往会出现这样的问题,由于刚开始无法估计需要的磁盘空间,导致后期磁盘空间不够,使得数据没地方存储,又或者后期磁盘空间过大,造成资源的浪费.这种在使 ...