并发编程 Process 互斥锁
进程理论
程序与进程的区别
'''
程序不是存在硬盘上的代码,相对来说是静态的
进程表示程序在执行的过程,是动态的
'''
进程的调度
先来先服务调度算法
'''对长作业有利,对短作业无益'''
短作业优先调度算法
'''对短作业有利,长作业无益'''
两对重要的概念
同步和异步
'''描述的是任务的提交方式'''
同步:任务提交之后,原地等待任务的返回结果,等待过程中不做任何事情程序表面上表现出来的感觉就是卡住了
异步:任务提交之后,不原地等待任务返回的结果,直接去做其他事情
事后,任务的返回结果会有一个任务回调机制自动处理
阻塞和非阻塞
'''描述的是程序的运行状态'''
阻塞:阻塞态
非阻塞:就绪态、运行态
上述概念的组合:最高效的一种组合就是异步非阻塞
开启进程的方式
from multiprocessing import Process
import time
def task(name):
print('%s is running' % name)
time.sleep(3)
print('%s is over'%name)
if __name__ == '__main__':
# 1、创建一个对象 target=>要执行的任务
p = Process(target=task,args=('卡卡西里',))
# 容器类型哪怕里面只有一个元素 建议要用逗号隔开
# 2 开启进程
p.start() # 告诉系统帮你创建一个进程 异步
print('主进程')
总结
'''创建进程就是在内存中申请一块内存空间将需要运行的代码丢进去
一个进程对应在内存中就是一块独立的内存空间
多个进程对应在内存中就是多块独立的内存空间
进程与进程之间默认情况下是无法直接交互的,想要交互借助于第三方工具、模块
'''
join方法
jion 是让其他主进程等待子进程代码运行结束之后,再继续运行。不影响其他子进程的执行
from multiprocessing import Process
import time
def task(name):
print('%s is running' % name)
time.sleep(3)
print('%s is over' % name)
if __name__ == '__main__':
p1 = Process(target=task, args=('卡卡西里1',))
p2 = Process(target=task, args=('卡卡西里2',))
p3 = Process(target=task, args=('卡卡西里3',))
start = time.time()
p1.start()
p2.start()
p3.start()
p1.join()
p2.join()
p3.join()
print('主进程',time.time()-start)
'''输出结果
卡卡西里2 is running
卡卡西里1 is running
卡卡西里3 is running
卡卡西里2 is over
卡卡西里1 is over
卡卡西里3 is over
主进程 3.0681638717651367
'''
# for 循环 开启进程 join
from multiprocessing import Process
import time
def task(name, n):
print('%s is running' % name)
time.sleep(n)
print('%s is over' % name)
if __name__ == '__main__':
p_list = []
start = time.time()
for i in range(1,4):
p = Process(target=task, args=('进程%s' % i, i))
p.start()
p_list.append(p)
for p in p_list:
p.join()
print('主进程', time.time() - start)
Process参数
Process的父类里面的属性要传以下参数
'''group=None, target=None, name=None, args=(), kwargs={},
*, daemon=None'''
# target表示的是需要执行的任务,或函数
# name表示的是进程的名字 不传入的话,默认名字是Process-1 后面依次递增
# 也可以传值进行修改
p1 = Process(target=task,name='kakaxili_1' args=('卡卡西里1',))
# args 传入的是元组,传的是任务函数需要的参数 按位置传入
# kwargs 闯入的是字典,传的是任务函数需要的参数,关键字传入
Process类方法
p.start() 开启进程
p.join() jion 是让其他主进程等待子进程代码运行结束之后,再继续运行。不影响其他子进程的执行
p.run() 没有开启子进程,而是把它当作一个进程执行了,相当于串行了
p.termainate() 终止该进程,但是需要时间
p.is_alive() 判断进程是否存活,存活返回True,否则返回False
Process属性
p.pid p进程的id 在主进程中查看的
p.name p进程的进程名称
p.daemon = True daemon默认传入的是False 设为True设置守护进程,主进程如果运行结束,子进程也跟着结束,但是必须放在start之前
获取进程ID的方法
import os
def func():
print(os.getpid()) # 获取当前进程的id
print(os.getppid()) # 获取父进程的id
互斥锁
在python的多线程和多进程中,当我们需要对多线程或多进程的共享资源或对象进行修改操作时,往往会出现因cpu随机调度而导致结果和我们预期不一致的问题,这时就需要对线程或者进程加锁,以保证一个线程或进程在对共享对象进行修改时,其他的线程或进程无法访问这个对象,直至获取锁的线程的操作执行完毕后释放锁。所以,锁在多线程和多进程中起到一个同步的作用,以保护每个线程和进程必要操作的完整执行。
import multiprocessing
import os
import time
from multiprocessing import Process, Lock
def task(i, lock):
lock.acquire() # 获得锁
print('%s号进程,ID:%s 开始执行' % (i, os.getpid()))
time.sleep(2)
print('%s号进程,ID:%s 执行结束' % (i, os.getpid()))
lock.release() # 释放锁
if __name__ == '__main__':
# 实例化得到一把锁
multiprocessing.set_start_method('fork') # mac 解决办法
lock = Lock()
for i in range(1, 5):
p = Process(target=task, args=(i, lock))
p.start()
学习Python3 互斥锁遇到的mac系统遇到的错误 FileNotFoundError: [Errno 2] No such file or directory
mac系统
python3.4更新后,默认用“spawn”,开启进程,我们要主动指定为“fork”
spawn:使用此方式启动的进程,只会执行和 target 参数或者 run() 方法相关的代码。Windows 平台只能使用此方法,事实上该平台默认使用的也是该启动方式。相比其他两种方式,此方式启动进程的效率最低。
fork:使用此方式启动的进程,基本等同于主进程(即主进程拥有的资源,该子进程全都有)。因此,该子进程会从创建位置起,和主进程一样执行程序中的代码。注意,此启动方式仅适用于 UNIX 平台,os.fork() 创建的进程就是采用此方式启动的。
forserver:使用此方式,程序将会启动一个服务器进程。即当程序每次请求启动新进程时,父进程都会连接到该服务器进程,请求由服务器进程来创建新进程。通过这种方式启动的进程不需要从父进程继承资源。注意,此启动方式只在 UNIX 平台上有效。
在实例化锁之前添加
multiprocessing.set_start_method('fork')
并发编程 Process 互斥锁的更多相关文章
- python 并发编程 多进程 互斥锁 目录
python 并发编程 多进程 互斥锁 模拟抢票 互斥锁与join区别
- python 并发编程 多进程 互斥锁与join区别
互斥锁与join 互斥锁和join都可以把并发变成串行 以下代码是用join实现串行 from multiprocessing import Process import time import js ...
- python 并发编程 多进程 互斥锁
运行多进程 每个子进程的内存空间是互相隔离的 进程之间数据不能共享的 一 互斥锁 但是进程之间都是运行在一个操作系统上,进程之间数据不共享,但是共享同一套文件系统,所以访问同一个文件,或同一个打印终 ...
- c++并发编程之互斥锁(mutex)的使用方法
1. 多个线程访问同一资源时,为了保证数据的一致性,最简单的方式就是使用 mutex(互斥锁). 引用 cppreference 的介绍: The mutex class is a synchroni ...
- python 并发编程 多线程 互斥锁
互斥锁 并行变成串行,牺牲效率 保证数据安全,实现局部串行 保护不同的数据,应该加不同的锁 现在一个进程 可以有多个线程 所有线程都共享进程的地址空间 实现数据共享 共享带来问题就会出现竞争 竞争就会 ...
- C++ 并发编程之互斥锁和条件变量的性能比较
介绍 本文以最简单生产者消费者模型,通过运行程序,观察该进程的cpu使用率,来对比使用互斥锁 和 互斥锁+条件变量的性能比较. 本例子的生产者消费者模型,1个生产者,5个消费者. 生产者线程往队列里放 ...
- Java并发编程:Concurrent锁机制解析
Java并发编程:Concurrent锁机制解析 */--> code {color: #FF0000} pre.src {background-color: #002b36; color: # ...
- Python之路(第三十八篇) 并发编程:进程同步锁/互斥锁、信号量、事件、队列、生产者消费者模型
一.进程锁(同步锁/互斥锁) 进程之间数据不共享,但是共享同一套文件系统,所以访问同一个文件,或同一个打印终端,是没有问题的, 而共享带来的是竞争,竞争带来的结果就是错乱,如何控制,就是加锁处理. 例 ...
- 并发编程: GIL锁、GIL与互斥锁区别、进程池与线程池的区别
一.GIL 二.关于GIL性能的讨论 三.计算密集测试 四.IO密集测试 五.GIL与互斥锁 六.TCP客户端 七.进程池 八.进程什么时候算是空闲 九.线程池 一.GIL GIL Global In ...
随机推荐
- git常用命令自己梳理总结
一.新建代码库 # git-init - 创建一个空的 Git 存储库或重新初始化一个现有的存储库 $ git init # 在本地新建一个repo,进入一个项目目录,执行git init,会初始化一 ...
- Linux从头学03:如何告诉 CPU,代码段、数据段、栈段在内存中什么位置?
作 者:道哥,10+年的嵌入式开发老兵. 公众号:[IOT物联网小镇],专注于:C/C++.Linux操作系统.应用程序设计.物联网.单片机和嵌入式开发等领域. 公众号回复[书籍],获取 Linux. ...
- YAOI Round #1 题解
前言 比赛网址:http://47.110.12.131:9016/contest/3 总体来说,这次比赛是有一定区分度的, \(\text{ACM}\) 赛制也挺有意思的. 题解 A. 云之彼端,约 ...
- Django 基础05篇 上下文管理和前端代码复用
一.上下文管理器 在views中重复使用的代码,可以通过上下文管理器(在setting.py文件中的TEMPLATES中配置)中实现,减少代码冗余 上下文管理器的处理流程如下: 1.先走完views里 ...
- python使用笔记17--异常处理
什么是异常? 异常即是一个事件,该事件会在程序执行过程中发生,影响了程序的正常执行. 一般情况下,在Python无法正常处理程序时就会发生一个异常. 异常是Python对象,表示一个错误. 当Pyth ...
- k8s之deployment详解
Deployment介绍 为了更好地解决服务编排的问题,k8s在V1.2版本开始,引入了deployment控制器,值得一提的是,这种控制器并不直接管理pod, 而是通过管理replicaset来间接 ...
- C语言typedef的用法详解
C语言允许为一个数据类型起一个新的别名,就像给人起"绰号"一样. 起别名的目的不是为了提高程序运行效率,而是为了编码方便.例如有一个结构体的名字是 stu,要想定义一个结构体变量就 ...
- SpringMVC架构(一)
SpringMVC架构 1.1Spring web mvc介绍 Spring web mvc和Struts2都属于表现层的框架,它是Spring框架的一部分,我们可以从Spring的整体结构中看得出来 ...
- SpringBoot 整合 MybatisPlus 3.0
CRUD是指在做计算处理时的增加(Create).读取查询(Retrieve).更新(Update)和删除(Delete)几个单词的首字母简写.主要被用在描述软件系统中DataBase或者持久层的 ...
- 【LeetCode】974. 和可被 K 整除的子数组
974. 和可被 K 整除的子数组 知识点:数组:前缀和: 题目描述 给定一个整数数组 A,返回其中元素之和可被 K 整除的(连续.非空)子数组的数目. 示例 输入:A = [4,5,0,-2,-3, ...