java 从零实现属于你的 redis 分布式锁

点赞再看 , 已成习惯 。
java 从零实现属于你的 redis 分布式锁文章插图
redis分布式锁
为什么需要分布式锁在 jdk 中为我们提供了加锁的方式:
(1)synchronized 关键字
(2)volatile + CAS 实现的乐观锁
(3)ReadWriteLock 读写锁
(4)ReenTrantLock 可重入锁
等等 , 这些锁为我们变成提供极大的便利性 , 保证在多线程的情况下 , 保证线程安全 。
但是在分布式系统中 , 上面的锁就统统没用了 。
我们想要解决分布式系统中的并发问题 , 就需要引入分布式锁的概念 。
java 从零实现属于你的 redis 分布式锁文章插图
分布式锁
上一节我们已经对分布式锁原理进行了详细讲解 , 参见:
redis 分布式锁原理详解
java 代码实现创作动机首先是对锁实现原理的一个实现 , 理论指导实践 , 实践完善理论 。
晚上关于 redis 分布式锁的文章一大堆 , 但是也都稂莠不齐 。
redis 分布式锁工具有时候中间件团队不见得会提供 , 提供了也不见得经常维护 , 不如自己实现一个 , 知道原理 , 也方便修改 。
接口定义为了便于和 JDK 复用 , 我们让接口继承自 jdk 的 Lock 接口 。
package com.github.houbb.lock.api.core;import java.util.concurrent.TimeUnit;import java.util.concurrent.locks.Lock;/** * 锁定义 * @author binbin.hou * @since 0.0.1 */public interface ILock extends Lock {/*** 尝试加锁* @param time 时间* @param unit 当为* @param key key* @return 返回* @throws InterruptedException 异常* @since 0.0.1*/boolean tryLock(long time, TimeUnit unit,String key) throws InterruptedException;/*** 尝试加锁* @param key key* @return 返回* @since 0.0.1*/boolean tryLock(String key);/*** 解锁* @param key key* @since 0.0.1*/void unlock(String key);}方法我们只添加了三个比较常用的核心方法 , 作为第一个版本 , 简单点 。
后续陆续添加即可 。
抽象实现为了便于后期添加更多的所实现 , 这里首先实现了一个公用的抽象父类 。
package com.github.houbb.lock.redis.core;import com.github.houbb.lock.api.core.ILock;import com.github.houbb.lock.redis.constant.LockRedisConst;import com.github.houbb.wait.api.IWait;import java.util.concurrent.TimeUnit;import java.util.concurrent.locks.Condition;/** * 抽象实现 * @author binbin.hou * @since 0.0.1 */public abstract class AbstractLockRedis implements ILock {/*** 锁等待* @since 0.0.1*/private final IWait wait;protected AbstractLockRedis(IWait wait) {this.wait = wait;}@Overridepublic void lock() {throw new UnsupportedOperationException();}@Overridepublic void lockInterruptibly() throws InterruptedException {throw new UnsupportedOperationException();}@Overridepublic boolean tryLock() {return tryLock(LockRedisConst.DEFAULT_KEY);}@Overridepublic void unlock() {unlock(LockRedisConst.DEFAULT_KEY);}@Overridepublic boolean tryLock(long time, TimeUnit unit, String key) throws InterruptedException {long startTimeMills = System.currentTimeMillis();// 一次获取 , 直接成功boolean result = this.tryLock(key);if(result) {return true;}// 时间判断if(time <= 0) {return false;}long durationMills = unit.toMillis(time);long endMills = startTimeMills + durationMills;// 循环等待while (System.currentTimeMillis()