Python锁机制如何理解,RLock()与Lock()有何不同
Admin 2022-08-03 群英技术资讯 863 次浏览
在这篇文章中,我们来学习一下“Python锁机制如何理解,RLock()与Lock()有何不同”的相关知识,下文有详细的讲解,易于大家学习和理解,有需要的朋友可以借鉴参考,下面就请大家跟着小编的思路一起来学习一下吧。要回答这个问题,我们需要知道为什么需要使用锁机制。前面我们谈到一个进程内的多个线程的某些资源是共享的,这也是线程的一大优势,但是也随之带来一个问题,即当两个及两个以上的线程同时访问共享资源时,如果此时没有预设对应的同步机制,就可能带来同一时刻多个线程同时访问同一个共享资源,即出现竞态,多数情况下我们是不希望出现这样的情况的,那么怎么避免呢?
先看一段代码:
import threading
import time
resource = 0
count = 1000000
resource_lock = threading.Lock()
def increment():
global resource
for i in range(count):
resource += 1
def decerment():
global resource
for i in range(count):
resource -= 1
increment_thread = threading.Thread(target=increment)
decerment_thread = threading.Thread(target=decerment)
increment_thread.start()
decerment_thread.start()
increment_thread.join()
decerment_thread.join()
print(resource)
运行截图如下:

运行结果
当我们多次运行时,可以看到最终的结果都几乎不等于我们期待的值即resource初始值0。
为什么呢? 原因就是因为 += 和 -=并不是原子操作。
可以使用dis模块查看字节码:
import dis
def add(total):
total += 1
def desc(total):
total -= 1
total = 0
print(dis.dis(add))
print(dis.dis(desc))
# 运行结果:
# 3 0 LOAD_FAST 0 (total)
# 3 LOAD_CONST 1 (1)
# 6 INPLACE_ADD
# 7 STORE_FAST 0 (total)
# 10 LOAD_CONST 0 (None)
# 13 RETURN_VALUE
# None
# 5 0 LOAD_FAST 0 (total)
# 3 LOAD_CONST 1 (1)
# 6 INPLACE_SUBTRACT
# 7 STORE_FAST 0 (total)
# 10 LOAD_CONST 0 (None)
# 13 RETURN_VALUE
# None
那么如何保证初始值为0呢? 我们可以利用Lock(),代码如下:
import threading
import time
resource = 0
count = 1000000
resource_lock = threading.Lock()
def increment():
global resource
for i in range(count):
resource_lock.acquire()
resource += 1
resource_lock.release()
def decerment():
global resource
for i in range(count):
resource_lock.acquire()
resource -= 1
resource_lock.release()
increment_thread = threading.Thread(target=increment)
decerment_thread = threading.Thread(target=decerment)
increment_thread.start()
decerment_thread.start()
increment_thread.join()
decerment_thread.join()
print(resource)
运行截图如下:

运行结果
从运行结果可以看到,不论我们运行多少次改代码,其resource的值都为初始值0, 这就是Lock()的功劳,即它可以将某一时刻的访问限定在单个线程或者单个类型的线程上,在访问锁定的共享资源时,必须要现获取对应的锁才能访问,即要等待其他线程释放资源,即resource_lock.release()当然为了防止我们对某个资源锁定后,忘记释放锁,导致死锁,我们可以利用上下文管理器管理锁实现同样的效果:
import threading
import time
resource = 0
count = 1000000
resource_lock = threading.Lock()
def increment():
global resource
for i in range(count):
with resource_lock:
resource += 1
def decerment():
global resource
for i in range(count):
with resource_lock:
resource -= 1
increment_thread = threading.Thread(target=increment)
decerment_thread = threading.Thread(target=decerment)
increment_thread.start()
decerment_thread.start()
我们需要知道Lock()作为一个基本的锁对象,一次只能一个锁定,其余锁请求,需等待锁释放后才能获取,否则会发生死锁:
import threading resource.lock = threading.lock() resource = 0 resource.lock.acquire() resource.lock.acquire() resource += 1 resource.lock.release() resource.lock.release()
为解决同一线程中不能多次请求同一资源的问题,python提供了“可重入锁”:threading.RLock,RLock内部维护着一个Lock和一个counter变量,counter记录了acquire的次数,从而使得资源可以被多次acquire。
直到一个线程所有的acquire都被release,其他的线程才能获得资源 。用法和threading.Lock类相同,即比如递归锁的使用:
import threading
lock = threading.RLock()
def dosomething(lock):
lock.acquire()
# do something
lock.release()
lock.acquire()
dosomething(lock)
lock.release()
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:mmqy2019@163.com进行举报,并提供相关证据,查实之后,将立刻删除涉嫌侵权内容。
猜你喜欢
Python例子-计算阶乘 n! = 1 * 2 * 3 * ... * n。两种方法,一种是用while循环实现,另一种是用递归函数实现
这篇文章主要介绍了Python实现用手机监控远程控制电脑的方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
这篇文章主要为大家介绍了pytorch深度神经网络入门准备自己的图片数据示例过程,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
这篇文章主要介绍了初识python的numpy模块,Numpy基于更加现代化的编程语言--python,python凭借着开源、免费、灵活性、简单易学、工程特性好等特点风靡技术圈,已经成为机器学习、数据分析等领域的主流编程语言,需要的朋友可以参考下
这篇文章主要介绍了通过OpenCV MediaPipe实现摄像头实时检测颜值打分功能,文中的示例代码讲解详细,对我们学习Python有一定的帮助,感兴趣的可以了解一下
成为群英会员,开启智能安全云计算之旅
立即注册关注或联系群英网络
7x24小时售前:400-678-4567
7x24小时售后:0668-2555666
24小时QQ客服
群英微信公众号
CNNIC域名投诉举报处理平台
服务电话:010-58813000
服务邮箱:service@cnnic.cn
投诉与建议:0668-2555555
Copyright © QY Network Company Ltd. All Rights Reserved. 2003-2020 群英 版权所有
增值电信经营许可证 : B1.B2-20140078 ICP核准(ICP备案)粤ICP备09006778号 域名注册商资质 粤 D3.1-20240008