后端开发应彻底掌握的13 种锁的实现方式

本文详细介绍了后端开发中常见的13种锁机制,包括悲观锁、乐观锁、分布式锁、可重入锁、自旋锁、独享锁、共享锁、读锁/写锁、公平锁/非公平锁、可中断锁/不可中断锁、分段锁、锁升级(无锁|偏向锁|轻量级锁|重量级锁)以及锁优化技术。通过对这些锁的理解和应用,开发者可以更好地解决并发控制和资源互斥问题,提升分布式系统性能。
摘要由CSDN通过智能技术生成

最近有很多小伙伴给我留言,分布式系统时代,线程并发,资源抢占,"锁" 慢慢变得很重要。那么常见的锁都有哪些?

今天就和大家简单聊聊这个话题

1、悲观锁

正如其名,它是指对数据修改时持保守态度,认为其他人也会修改数据。因此在操作数据时,会把数据锁住,直到操作完成。悲观锁大多数情况下依靠数据库的锁机制实现,以保证操作最大程度的独占性。如果加锁的时间过长,其他用户长时间无法访问,影响程序的并发访问性,同时这样对数据库性能开销影响也很大,特别是长事务而言,这样的开销往往无法承受。

如果是单机系统,我们可以采用 JAVA 自带的 synchronized 关键字,通过添加到方法或同步块上,锁住资源 如果是分布式系统,我们可以借助数据库自身的锁机制来实现

select * from 表名 where id= #{id} for update

使用悲观锁的时候,我们要注意锁的级别,MySQL innodb 在加锁时,只有明确的指定主键或(索引字段)才会使用 行锁;否则,会执行 表锁,将整个表锁住,此时性能会很差。在使用悲观锁时,我们必须关闭 MySQL 数据库的自动提交属性,因为mysql默认使用自动提交模式。悲观锁适用于写多的场景,而且并发性能要求不高

2、乐观锁

乐观锁,从字面意思也能猜到个大概,在操作数据时非常乐观,认为别人不会同时修改数据,因此乐观锁不会上锁 只是在 提交更新 时,才会正式对数据的冲突与否进行检测。如果发现冲突了,则返回错误信息,让用户决定如何去做,fail-fast 机制 。否则,执行本次操作。

分为三个阶段:数据读取、写入校验、数据写入。

如果是单机系统,我们可以基于JAVA 的 CAS来实现,CAS 是一种原子操作,借助硬件的比较并交换来实现。

如果是分布式系统,我们可以在数据库表中增加一个 版本号 字段,如:version

update 表 
set ... , version = version +1 
where id= #{id} and version = #{version} 

操作前,先读取记录的版本号,更新时,通过SQL语句比较版本号是否一致。如果一致,则更新数据。否则会再次读取版本,重试上面的操作。

3、分布式锁

synchronized 、ReentrantLock 等,都是解决单体应用单机部署的资源互斥问题。随着业务快速发展,当单体应用演化为分布式集群后,多线程、多进程分布在不同的机器上,原来的单机并发控制锁策略失效

此时我们需要引入 分布式锁,解决跨机器的互斥机制来控制共享资源的访问。

分布式锁需要具备哪些条件:

  • 与单机系统一样的资源互斥功能,这是锁的基础

  • 高性能获取、释放锁

  • 高可用

  • 具备可重入性

  • 有锁失效机制,防止死锁

  • 非阻塞,不管是否获得锁,要能快速返回

实现方式多种多样,基于 数据库、Redis、以及 Zookeeper等,这里讲下主流的基于Redis的实现方式:

加锁:

SET key unique_value  [EX seconds] [PX milliseconds] [NX|XX]

通过原子命令,如果执行成功返回 1,则表示加锁成功。注意:unique_value 是客户端生成的唯一标识,区分来自不同客户端的锁操作 解锁要特别注意,先判断 unique_value 是不是加锁的客户端,是的话才允许解锁删除。毕竟我们不能删除其他客户端加的锁。

解锁:解锁有两个命令操作,需要借助 Lua 脚本来保证原子性。

// 先比较 unique_value 是否相等,避免锁的误释放
if redis.call("get",KEYS[1]) == ARGV[1] then
    return redis.call("del",KEYS[1])
else
    return 0
end

借助 Redis 的高性能

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值