暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

Lock与RLock的区别

AI有温度 2021-08-31
2379
B站同名【有温度的算法】已经上线
想观看视频讲解的同学
在文末点击【原文链接】直达B站


在上节中为大家说明了线程访问临界资源,必须互斥的进行,从而引出了锁。在Python的threading模块中,为我们提供了Lock方法与RLock方法,都具备锁的功能,本节就为大家介绍一下两者在应用时的不同。

区别一

Lock被称为原始锁,一个线程只能请求一次;RLock被称为重入锁,可以被一个线程请求多次,即锁中可以嵌套锁,所以在使用RLock时,acquire与release必须成对出现。
import threading


def main():
lock.acquire()
print('第一道锁')
lock.acquire()
print('第二道锁')
lock.release()
lock.release()


if __name__ == '__main__':
lock = threading.Lock()
main()
复制
我们定义Lock锁,同时在main函数中定义2个锁,在进入第一个锁后打印“第一道锁”,在进入第二个锁后打印“第二道锁”,然后在主线程中运行(只有这一个线程)。
# 输出
第一道锁
复制
我们会发现这时程序只会打印“第一道锁”,而且程序既没有终止,也没有继续运行。这是因为Lock锁在同一线程内第一次加锁之后还没有释放时,就进行了第二次acquire请求,导致无法执行release,所以锁永远无法释放,这就是死锁。
import threading


def main():
lock.acquire()
print('第一道锁')
lock.acquire()
print('第二道锁')
lock.release()
lock.release()
if __name__ == '__main__':
lock = threading.RLock()
main()
复制
如果我们使用RLock,就不会发生死锁的状态。
# 输出
第一道锁
第二道锁
复制
因为RLock可以被一个线程请求多次,即锁中可以嵌套锁。

区别二

当Lock处于锁定状态时,不属于特定线程,可在另一个线程中进行解锁释放;而RLock只有当前线程才能释放本线程上的锁,不可由其他线程进行释放,所以在使用RLock时,acquire与release必须成对出现,即解铃还须系铃人。
import threading


def main():
lock.release()
print("在子线程解锁后打印")
if __name__ == '__main__':
lock = threading.Lock()
lock.acquire()
t = threading.Thread(target=main)
t.start()
复制
在主线程中定义Lock锁,然后上锁,再创建一个子线程t运行main函数释放锁,结果正常输出,说明主线程上的锁,可由子线程解锁。
# 输出
在子线程解锁后打印
复制
如果把上面的锁改为RLock则报错。在实际中设计程序时,我们会将每个功能分别封装成一个函数,每个函数中都可能会有临界区域,所以就需要用到RLock。
import threading
import time


def fun_1():
print('开始')
time.sleep(1)
lock.acquire()
print("第一道锁")
fun_2()
lock.release()


def fun_2():
lock.acquire()
print("第二道锁")
lock.release()


if __name__ == '__main__':
lock = threading.RLock()
t1 = threading.Thread(target=fun_1)
t2 = threading.Thread(target=fun_1)
t1.start()
t2.start()
复制
我们定义RLock锁,然后设置t1与t2两个线程,两个线程分别运行fun_1,都打印“开始”,然后进入到临界区域,fun_1先上锁后打印“第一道锁”,然后进入fun_2,上第二道锁后打印“第二道锁”,之后解除第二道锁再解除第一道锁后执行结束。t2在t1上锁后被堵塞,等t1完全解锁后t2才继续运行。
# 输出
开始
开始
第一道锁
第二道锁
第一道锁
第二道锁
复制
如果此例用Lock锁的话,由于在同一线程中fun_1上了一把锁,在进入fun_2中会因为无法第二次上锁而导致本线程阻塞,程序阻塞之后又无法释放锁,就会导致程序死锁。在实际的复杂程序中,RLock使用的更多一些。 

往期推荐



Python多线程的使用

Python线程池的使用

Python多线程的安全问题

获取多线程相关代码
在后台回复【多线程】即可获取
点击【阅读全文】直达B站
文章转载自AI有温度,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论