<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.xin.mapper.LocksMapper">
<update id="updateLockVersion">
update t_lock set version=version+1,timeout=0,request_id=#{requestId},lock_count=#{lockCount} where lock_key=#{lockKey} and version =#{version}
</update>
<select id="getLock" resultType="com.xin.entity.LocksEntity">
select * from t_lock where lock_key=#{lockKey} for update
</select>
</mapper>
/*
package com.xin.utils; import com.xin.entity.LocksEntity; import com.xin.service.LocksService; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.stereotype.Component; import javax.annotation.Resource; import java.util.UUID; @Component public class LockVersion { @Resource private LocksService locksService; private ThreadLocal<String> threadLocal = new ThreadLocal<>(); @Resource private RedisTemplate redisTemplate; /** * * @param lockKey 锁的标识 * @param timeOut 获取锁的超时时间 * @param possessTime 持有锁的时间 * @return */ public boolean getLock(String lockKey,Long timeOut,Long possessTime) throws InterruptedException { String requireKey = this.getRequireKey(); Long startTime = System.currentTimeMillis(); while (true) { //获取锁对象 LocksEntity lock = this.locksService.getLock(lockKey); //创建一个锁对象,并且自己尝试去获取该锁对象 if (lock==null){ if (this.redisTemplate.boundValueOps(lockKey).setIfAbsent(lockKey)){ LocksEntity locksEntity = new LocksEntity(lockKey,"",0,0L,0); this.locksService.add(locksEntity); } } else { //说明当前锁没有被其他线程持有 if (lock.getRequestId()==null||lock.getRequestId().equals("")){ System.out.println("当前线程没有被其他线程持有"); lock.setRequestId(requireKey); lock.setTimeout(possessTime+System.currentTimeMillis()); lock.setLockCount(lock.getLockCount()+1); //使用数据库乐观锁 Integer integer = this.locksService.updateLockVersion(lock); if (integer>=1) return true; else Thread.sleep(100); } //说明当前锁被自己持有 else if (lock.getRequestId()!=null&&lock.getRequestId().equals(requireKey)){ System.out.println("进行锁重入"); //进行一个锁的重入 lock.setLockCount(lock.getLockCount()+1); //使用数据库乐观锁 Integer integer = this.locksService.updateLockVersion(lock); if (integer>=1) return true; else Thread.sleep(100); } //说明当前锁不是被自己持有,被其他线程持有 else { //判断其他线程持有锁的时间是否超时 if (lock.getTimeout()>System.currentTimeMillis()){ System.out.println("其他线程持有锁超时"); //重置锁 lock.setLockCount(0); lock.setVersion(0); lock.setTimeout(0L); lock.setRequestId(""); this.locksService.updateById(lock); } //判断自己获取是否已经超时 if (timeOut+startTime>System.currentTimeMillis()){ System.out.println("自己获取锁超时"); return false; } } } } } /** * 释放锁 * @param lockKey * @return */ public boolean unLock(String lockKey){ String requireKey = getRequireKey(); LocksEntity lock = this.locksService.getLock(lockKey); //判断自己是否锁的持有者 if (requireKey.equals(lock.getRequestId())){ lock.setVersion(0); lock.setTimeout(0L); lock.setLockCount(0); lock.setRequestId(""); boolean b = this.locksService.updateById(lock); if (b) return true; } return false; } /** * 获取请求key * @return */ public String getRequireKey(){ String key = threadLocal.get(); if (key==null){ key= UUID.randomUUID().toString(); threadLocal.set(key); } return key; } }
Navicat Premium Data TransferSource Server : Product
Source Server Type : MySQL
Source Server Version : 80022
Source Host : localhost:3306
Source Schema : javacode2018Target Server Type : MySQL
Target Server Version : 80022
File Encoding : 65001Date: 02/12/2023 15:13:49
*/SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;-- ----------------------------
-- Table structure for t_lock
-- ----------------------------
DROP TABLE IF EXISTS `t_lock`;
CREATE TABLE `t_lock` (
`id` bigint(0) NOT NULL AUTO_INCREMENT,
`lock_key` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '锁唯一标志',
`request_id` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL DEFAULT '' COMMENT '用来标识请求对象的',
`lock_count` int(0) NOT NULL DEFAULT 0 COMMENT '当前上锁次数',
`timeout` bigint(0) NOT NULL DEFAULT 0 COMMENT '锁超时时间',
`version` int(0) NOT NULL DEFAULT 0 COMMENT '版本号,每次更新+1',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 1729784763572424705 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '锁信息表' ROW_FORMAT = Dynamic;SET FOREIGN_KEY_CHECKS = 1;