python基础——锁

进程锁 (互斥锁)

进程锁的引入:

模拟抢票程序:

from multiprocessing import Process
import json
import time
def show_ticket(i):with open("./tickets.txt",mode="r",encoding="utf-8") as file:ticket = json.load(file)print("{}:当前的票数是:{}".format(i,ticket['count']))
def buy_ticket(i):with open("./tickets.txt",mode="r",encoding="utf-8") as file:ticket = json.load(file)if ticket['count'] > 0:ticket['count'] -= 1print("{}买到票了".format(i))else:print("票卖完了")time.sleep(0.1)with open("./tickets.txt",mode="w",encoding="utf-8") as new_file:json.dump(ticket,new_file)if __name__ == '__main__':for i in range(10):Process(target=show_ticket,args=(i,)).start()Process(target=buy_ticket,args=(i,)).start()

运行结果:

实际仅有一张票,但是由于系统的并发执行速度较快,导致系统出现错误

此时,就需要使用锁来进行数据保护,防止出现数据上的错误

进程锁的使用:

from multiprocessing import Process,Lock
import json
import time
def show_ticket(i,lock):lock.acquire()with open("./tickets.txt",mode="r",encoding="utf-8") as file:ticket = json.load(file)print("{}:当前的票数是:{}".format(i,ticket['count']))lock.release()
def buy_ticket(i,lock):lock.acquire()with open("./tickets.txt",mode="r",encoding="utf-8") as file:ticket = json.load(file)if ticket['count'] > 0:ticket['count'] -= 1print("{}买到票了".format(i))else:print("票卖完了")time.sleep(0.1)with open("./tickets.txt",mode="w",encoding="utf-8") as new_file:json.dump(ticket,new_file)lock.release()
if __name__ == '__main__':lock = Lock()for i in range(10):Process(target=show_ticket,args=(i,lock)).start()Process(target=buy_ticket,args=(i,lock)).start()

运行结果:

使用进程锁可以保证一次进运行一个进程,防止进程之间数据的错误

进程锁再次使用:

不使用进程锁:

from multiprocessing import Process
import time
from multiprocessing import Lock
def func1(i,lock):# lock.acquire()print("函数第{}次执行".format(i))time.sleep(1)print("函数执行完毕")# lock.release()
if __name__ == '__main__':lock = Lock()for i in range(10):Process(target=func1,args=(i,lock)).start()

执行结果:

使用进程锁:

from multiprocessing import Process
import time
from multiprocessing import Lock
def func1(i,lock):lock.acquire()print("函数第{}次执行".format(i))time.sleep(1)print("函数执行完毕")if __name__ == '__main__':lock = Lock()for i in range(10):Process(target=func1,args=(i,lock)).start()

执行结果:

注意:由于前者未使用进程锁,因此十个进程并发执行,总执行时间1s

后者使用进程锁,需要一个进程一个进程进行执行,因此总执行时间为10s

部分代码解释:

lock = Lock()   创建一个锁对象

lock.acquire()   表示该进程拿走锁,然后执行,阻塞其他进程

lock.release()  表示该进程执行完毕,归还锁,使得其他进程得以继续执行

此时,若果进程中只有lock.acquire()方法,而没有lock.release()方法,会使得程序阻塞,无法继续向下进行

from multiprocessing import Process
import time
from multiprocessing import Lock
def func1(i,lock):lock.acquire()print("函数第{}次执行".format(i))time.sleep(1)print("函数执行完毕")if __name__ == '__main__':lock = Lock()for i in range(10):Process(target=func1,args=(i,lock)).start()

执行结果:

另一种写法:

with lock:

代替lock.acquire()方法与lock.release()方法

线程锁              

线程锁的引入:

from threading import Thread
n = 0
def add():for i in range(2200000):global nn += 1
def sub():for i in range(2200000):global nn -= 1p1 = Thread(target=add)
p1.start()
p2 = Thread(target=sub)
p2.start()
p1.join()
p2.join()
print(n)

运行结果不确定,由于线程的执行速度过快,在同一时间,可能会有多个线程在进行加操作,而在加操作完成后,赋值操作仅进行了一次,因此出现数值的错误,因为错误次数不确定,因此运行的结果也不确定

部分运行结果:

线程中锁的使用:

from threading import Thread,Lock
n = 0
def add(lock):for i in range(2200000):global nlock.acquire()n += 1lock.release()
def sub(lock):for i in range(2200000):global nlock.acquire()n -= 1lock.release()
if __name__ == '__main__':lock = Lock()p1 = Thread(target=add,args=(lock,))p1.start()p2 = Thread(target=sub,args=(lock,))p2.start()p1.join()p2.join()print(n)

此时,无论程序执行多少次,数值的大小如何,由于锁的使用,每次的加运算与赋值运算都是单次进行,因此,数值不会出现错误

执行结果:

递归锁

在一个线程中可以进行多次acquire()操作

但同时,只有进行多次release()操作,才能解锁其他进程

递归锁的使用:

from threading import Thread,Lock,RLock
import time
n = 0
def add(lock):for i in range(2):global nlock.acquire()lock.acquire()n += 1time.sleep(1)print("函数add的执行次数{}".format(n))lock.release()
def sub(lock):for i in range(2):global nlock.acquire()n -= 1print("函数sub的执行次数{}".format(n))lock.release()
if __name__ == '__main__':lock = RLock()p1 = Thread(target=add,args=(lock,))p1.start()p2 = Thread(target=sub,args=(lock,))p2.start()p1.join()p2.join()print(n)

执行结果:

此时可以看到,由于函数add中上锁了两次,而只进行了一次解锁,因此在函数add执行完毕之后函数sub并不会进行执行

死锁现象

由于进程的执行顺序不当,或者资源的分配不当而导致整个进程不能进行执行,而陷入卡死的状态

死锁示例:

rom threading import Thread,Lock
import time
noodle_lock = Lock()
fork_lock = Lock()def eat(name):noodle_lock.acquire()print("{}抢到面了".format(name))fork_lock.acquire()print("{}抢到叉子了".format(name))print("{}吃面".format(name))time.sleep(0.1)fork_lock.release()print("{}放下了叉子".format(name))noodle_lock.release()print("{}放下面了".format(name))
def eat2(name):fork_lock.acquire()print("{}抢到了叉子".format(name))noodle_lock.acquire()print("{}抢到面了".format(name))print("{}吃面".format(name))time.sleep(0.1)noodle_lock.release()print("{}放下面了".format(name))fork_lock.release()print("{}放下叉子了".format(name))Thread(target=eat,args=(1,)).start()
Thread(target=eat2,args=(2,)).start()
Thread(target=eat,args=(3,)).start()
Thread(target=eat2,args=(4,)).start()

部分执行结果:

注:死锁现象只发生在多个进程且存在多个互斥锁的情况在,单个互斥锁的合理使用不会导致死锁现象的发生

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/645988.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

51-15 视频理解串讲—TimeSformer论文精读

今天读的论文题目是Is Space-Time Attention All You Need for Video Understanding? Facebook AI提出了一种称为TimeSformer视频理解的新架构,这个架构完全基于transformer,不使用卷积层。它通过分别对视频的时间和空间维度应用自注意力机制&#xff…

《动手学深度学习(PyTorch版)》笔记3.1

Chapter3 Linear Neural Networks 3.1 Linear Regression 3.1.1 Basic Concepts 我们通常使用 n n n来表示数据集中的样本数。对索引为 i i i的样本,其输入表示为 x ( i ) [ x 1 ( i ) , x 2 ( i ) , . . . , x n ( i ) ] ⊤ \mathbf{x}^{(i)} [x_1^{(i)}, x_2…

【机器学习】强化学习(七)-策略梯度算法-REINFORCE 训练月球着陆器代理(智能体)...

概 述 月球着陆器代理是一个模拟飞行器在月球表面着陆的环境,它有八个连续的状态变量,分别是水平坐标、垂直坐标、水平速度、垂直速度、角度、角速度、腿1触地、腿2触地。它有四个离散的动作,分别是什么都不做、发动左方向引擎、发动主引擎、…

gin如何实现热更新

什么是热更新? 一种不需要用户关闭应用或重新启动设备就能进行的软件更新技术。它可以快速地在线修复或升级应用程序的错误或功能,从而减少用户的等待时间并提高用户体验。 如何优雅停止服务? Go 1.8版本之后, http.Server 内置…

ZigBee学习——浅析协议栈

✨记录学习过程 文章目录 一、初识OSAL1.1 Z-Stack和Zigbee的OSAL是什么关系?1.2 OSAL可以解决Z-stack在不同厂商的芯片上的使用吗? 二、协议栈运行机制2.1 初始化涉及内容2.2 初始化过程 一、初识OSAL OSAL,全称是操作系统抽象层&#xff0…

【送书活动八期】docker容器中登陆并操作postgresql

这里的背景比较简单,因为区块链浏览器使用的是blockscout,blockscout的数据库选择的是postgresql,这些服务组件都是使用的docker容器来管理,今天进行区块链上交易查询的时候,发现数据存在部分问题,因此需要…

《WebKit 技术内幕》学习之十(4): 插件与JavaScript扩展

4 Chromium扩展机制 4.1 原理 Chromium的扩展(Extension)机制 (1) 原先是Chromium推出的一项技术,该机制能够扩展浏览器的能力,例如笔者使用的一个扩展实例名为“switchy proxy”,它可以帮助用户方便的切换Chromium…

Kotlin for loop: in、 until、 step、 downTo

Kotlin for loop: in、 until、 step、 downTo fun loop1() {for (i in 0..5) {print("$i ")}println("\n1-end\n") }fun loop2() {for (i in 0 until 5) {print("$i ")}println("\n2-end\n") }fun loop3() {for (i in 0 until (5)) {…

提高塑料制品的塑料透光率测量仪

塑料透光率检测仪是一种用于测量塑料材料透光率的仪器。透光率是指光线通过材料后,被吸收、反射和散射的量与总光线量的比例。塑料透光率检测仪在塑料制品的研发、生产和质量控制等方面具有广泛的应用。 塑料透光率检测仪的原理是使用光束通过待测塑料样品&#xff…

【神奇代码岛】VOXA新岛畅玩指南

前言 最近神奇代码岛不是迎来了重大更新嘛,有可能有很多人还不知道新版的神岛有什么重大更新,我现在来一一说明 重大更新 这一次我们将以代码、地图编辑器、建模编辑器来说明 代码 主要是增加了许多API,比如UI、玩家皮肤等许多新的API …

【推荐100个unity插件之16】3D物品描边效果——Quick Outline免费插件

文章目录 前言地址介绍使用例子完结 前言 关于3D描边,其实之前有用shader弄过一个:【实现100个unity特效】shader实现3D物品闪光和描边效果 但是很遗憾的是他不支持URP项目,所以现在推荐这款插件,他能很好的支持URP,…

Pycharm终端显示PS而不显示虚拟环境venv

PS表示当前使用的是powershell.exe,如果你要显示虚拟环境名,则要改为cmd.exe 解决办法: 打开File-settings-Tools-Terminal-shell path 在文件中找到设置,在工具中找到终端 把第四个Shell路径设置为cmd.exe 3. 点击确定&#xf…

springCloud的ribbon和feign

ribbon方式调用 就是将原来的具体地址,改为了通过服务名去调用。注册中心中有多个服务,相同服务名,就会算作可以调用的服务。 首先得有一个注册中心,然后各种服务注册进去,然后利用ribbon或者feign去调用。 ribbon是直…

map地图

地图想必大家都很熟悉,地图的应用非常广泛,我们出远门通常都会用到,下面我来给大家讲解一下地图! 首先我们要知道该怎样下载地图? 1.地图的版本有很多,我们选择一款,前往地图开发者中心。 2.…

《机器学习》客户流失判断-python实现

客户流失判断 题目赛题描述数据说明赛题来源-DataCastle 问题描述解题思路Python实现读取数据并初步了解导入宏包读取数据查看数据类型检查缺失值描述性统计分析 可视化分析用户流失分析特征分析任期年数与客户流失的关系:服务类属性分析特征相关性分析 数据预处理类…

༺༽༾ཊ—Unity之-01-单例模式—ཏ༿༼༻

在游戏开发过程中,我们会创建各种各样的类,再用new生成实例,有些时候我们需要这个类在整个游戏中是唯一出现的,比如一些管理器比如声音管理器等,没必要创建很多实例,就算有很多模块需要各种声音功能&#x…

信号量机制解决经典同步互斥问题

生产者 / 消费者问题、读者 / 写者问题和哲学家问题是操作系统的三大经典同步互斥问题。本文将介绍这三个问题的基本特点以及如何用信号量机制进行解决。 在分析这三个问题之前,我们首先需要了解用信号量机制解决同步互斥问题的一般规律: 实现同步与互斥…

制造领域 物料清单(BOM)与零件明细表的区别

有许多人分不清物料清单(BOM)与零件明细表的区别,其实它们在企业的生产管理软件中起着不同的作用,各有各的特色,但是却有不尽相同。接下来我们就来区分一下吧 物料清单(BOM),是详细记录一个项目所用到的所有下阶材料及相关属性,亦即母件与所有子件的从属…

求职应聘找工作,你一定会遇到的人才测评

信息时代,越来越多的公司在招聘时引入了人才测评机制。企业和单位希望通过人才测评在广大的应聘者中,找到符合自己要求的人才。虽然很多应聘者能力和简历都比较出众,但却在最开始的人才测评中吃了亏。有的公司很看重人才测评结果。测评就相当…

76.Go分布式ID总览

文章目录 简介一:UUID二、雪花算法三:Leaf-snowflake四:数据库自增ID五:使用Redis实现分布式ID生成六:使用数据库分段(Leaf-segment)七 :增强版Leaf-segment八:Tinyid九&…