AOP 实现分布式锁

在没有redis的情况下,本文介绍了如何通过AOP在MySQL数据库中实现分布式锁,以保证资源访问的互斥性。针对特定场景,即线程需要在资源状态为1时才能执行,并且同一时刻只允许一个线程执行,文章详细阐述了利用事务和加锁策略来防止不可重复读问题,包括定义DB锁接口、可重复锁实现、锁上下文、锁行为注解和锁切面的实现步骤。
摘要由CSDN通过智能技术生成

在web项目开发过程中,经常会遇到分布式资源控制的场景,通过加锁从而保证资源访问的互斥性。本文主要介绍在没有redis情况下通过mysql进行分布式锁的实现。

场景:

线程A与线程B执行前需要判断资源R的状态,当R的状态为1时,则可以执行,当R的状态为0时,则不容许执行,且同一时刻只容许一个线程执行。线程执行时资源R状态置0,线程执行结束后R状态重新置1.

上述场景中,若不对资源R进行互斥访问,则可能出现A、B线程同时访问资源R时且发现资源状态为1,从而都启动执行无法满足系统要求。

当资源R状态的获取和资源状态R的置位需要操作mysql进行实现时,我们则需要将查找和更新操作作为原子性操作,这种情况下,我们会考虑到事务,事务有如下几种隔离级别:

public enum Isolation {
     
    DEFAULT(-1),
    READ_UNCOMMITTED(1),
    READ_COMMITTED(2),
    REPEATABLE_READ(4),
    SERIALIZABLE(8);
}

而通常在web项目配置过程中,事务的隔离级别为READ_COMMITTED(2),可以避免脏读,依旧无法避免不可重复读。因此不可避免的需要将查找和更新操作进行加锁,同一时刻只允许一个线程访问操作。

AOP 实现

1.定义DB锁接口

public interface DBLock {
   

  /**
   * 加锁
   *
   * @param timeout 超时时间
   * @param expireTime 过期时间
   * @param timeUnit 时间单位
   * @return 是否加锁成功
   */
  default boolean lock(long timeout, long expireTime, TimeUnit timeUnit) {
   
    throw new ServerException("unimplemented function");
  }

  /**
   * 释放锁
   */
  default void unlock() {
   
    throw new ServerException("unimplemented function");
  }
}

2.可重复锁实现

@Slf4j
public class DBReentrantLock implements DBLock {
   

  /**
   * 锁资源
   */
  private LockService lockService;

  /**
   * 锁路径
   */
  private String lockPath;

  /**
   * 可重入数量
   */
  @Getter
  private int count = 0;

  /**
   * 过期时间
   */
  @Getter
  private long expireTime = 0;

  DBReentrantLock(LockService lockService, String lockPath) {
   
    this.lockService = lockService;
    this.lockPath = lockPath;
    this.count = 0;
  }

  /**
   * 获取锁
   *
   * @param timeout 超时时间
   * @param expireTime 过期时间
   * @param timeUnit 时间单位
   * @return 是否获取到锁
   */
  @Override
  public boolean lock(long timeout, long expireTime, TimeUnit timeUnit) {
   
    try {
   
      // 已获得锁
      if (this.count > 0) {
   
        this.count++;
        return true;
      }
      if (timeout < 0) 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值