当前位置: 首页 > news >正文

递归锁与普通锁的区别

什么是锁?

在多线程编程中,锁是一种机制,用来确保某些代码块在同一时间只能被一个线程执行。想象一下,你和你的朋友们都想同时进入一个只有一把椅子的房间。为了避免混乱,你们需要一个锁来控制进入的顺序。

普通锁(Lock)

普通锁就像是一个简单的门锁。你拿到钥匙(获取锁),进了房间(执行代码),然后记得把钥匙放回去(释放锁),这样别人才能进来。

让我们看看Python中的普通锁是如何工作的:

import threadinglock = threading.Lock()def critical_section():with lock:print(f"{threading.current_thread().name} has entered the critical section")# 模拟一些工作import timetime.sleep(1)print(f"{threading.current_thread().name} is leaving the critical section")threads = []
for i in range(3):thread = threading.Thread(target=critical_section)threads.append(thread)thread.start()for thread in threads:thread.join()

在这个例子中,我们创建了一个普通锁,并在critical_section函数中使用它。每个线程在进入关键区之前都会获取锁,并在离开时释放锁。这样可以确保同一时间只有一个线程在执行关键区的代码。

普通锁的死锁场景
普通锁虽然简单高效,但在某些情况下会导致死锁。让我们看看一个死锁的例子:

import threadinglock = threading.Lock()def deadlock_function():lock.acquire()print(f"{threading.current_thread().name} has acquired the lock")# 尝试再次获取同一把锁,导致死锁lock.acquire()print(f"{threading.current_thread().name} has acquired the lock again")lock.release()lock.release()thread = threading.Thread(target=deadlock_function)
thread.start()
thread.join()

在这个例子中,deadlock_function函数尝试两次获取同一把锁。第一次获取锁成功,但第二次获取锁时,由于锁已经被当前线程持有,导致死锁。程序会卡在第二次获取锁的地方,无法继续执行。

递归锁(Reentrant Lock)

递归锁就像是一个聪明的门锁,它知道你已经在房间里了,所以如果你再试图进入,它会让你进去,而不会把你锁在外面。这在递归函数或需要多次获取同一把锁的情况下特别有用。

让我们看看递归锁是如何工作的:

import threadingrlock = threading.RLock()def recursive_function(level):with rlock:print(f"{threading.current_thread().name} has entered level {level}")if level > 0:recursive_function(level - 1)print(f"{threading.current_thread().name} is leaving level {level}")thread = threading.Thread(target=recursive_function, args=(3,))
thread.start()
thread.join()

在这个例子中,我们使用了递归锁RLock。recursive_function函数会递归调用自己,并在每个递归层级获取同一把锁。递归锁允许同一个线程多次获取锁,而不会导致死锁。

递归锁 vs 普通锁

  • 普通锁:简单高效,但同一个线程不能多次获取同一把锁,否则会导致死锁。
  • 递归锁:允许同一个线程多次获取同一把锁,适用于递归调用或需要多次获取锁的情况,但开销稍大。

更清晰的案例

递归锁:

import threadingrecursive_lock = threading.RLock()def recursive_function(n):if n <= 0:returnrecursive_lock.acquire()print(f"Acquired lock, n={n}")recursive_function(n-1)recursive_lock.release()print(f"Released lock, n={n}")recursive_function(3)

输出:
Acquired lock, n=3
Acquired lock, n=2
Acquired lock, n=1
Released lock, n=1
Released lock, n=2
Released lock, n=3

普通锁:

import threadingrecursive_lock = threading.Lock()def recursive_function(n):if n <= 0:returnrecursive_lock.acquire()print(f"Acquired lock, n={n}")recursive_function(n-1)recursive_lock.release()print(f"Released lock, n={n}")recursive_function(3)

运行一天的输出:
Acquired lock, n=3

结论:

锁在多线程编程中是必不可少的工具。普通锁适用于简单的同步场景,而递归锁则在复杂的递归或多次锁定场景中大显身手。

http://www.lryc.cn/news/400813.html

相关文章:

  • FPGA上板项目(二)——PLL测试
  • C语言 | Leecode C语言题解之第229题多数元素II
  • mybatis-plus映射mysql的json类型的字段
  • 20240716 Codeforces题目
  • 29.【C语言】自定义函数
  • C++面向对象编程 基础篇(3)函数基础
  • excel有条件提取单元格特定文本(筛选纯文字的单元格或含有数字的单元格、单元格提取不同的文本长度)
  • HBase 在统一内容平台业务的优化实践
  • 【异常解决】Unable to start embedded Tomcat Nacos 启动报错
  • 【Java面向对象】对象和类
  • 在微服务架构架构中父工程中的`<dependencyManagement>`和 `<dependencies>`的区别
  • Docker安装Zookeeper、RocketMQ
  • Ubuntu 磁盘扩容
  • 如何在QGC中接收和处理无人机上传的各种传感器数据(如GPS、IMU等)。
  • Spring配置Bean自己的关系:继承和依赖
  • 科技与狠活
  • Vue:axios请求数据转存leanCloud
  • 实战篇(九):解锁3D魔方的秘密:用Processing编程实现交互式魔方
  • Android系统上常见的性能优化工具
  • TG创建小程序交互APP登录以及机器人信息
  • 探索大模型能力--prompt工程
  • 【经验分享】运用云服务器实现挂机手机网课的操作,部分手机软件适用
  • 【从0到1进阶Redis】主从复制 — 主从机宕机测试
  • Flask启动5000端口后关不掉了?
  • Redis的热key解决
  • 在linux中查找 / 目录下的以.jar结尾的文件(find / -name *.jar)
  • 【Python爬虫教程】第6篇-使用session发起请求
  • 【Hot100】LeetCode—763. 划分字母区间
  • 分布式服务基于Zookeeper的分布式锁的实现
  • Rust编程-I/O