单机redisson使用redis锁,遇到的问题记录
1.引入jar包
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> <dependency> <groupId>org.redisson</groupId> <artifactId>redisson</artifactId> <version>3.11.1</version> </dependency> <dependency> 复制代码
2.application.properties添加配置文件
server.port=8998 spring.redis.host=127.0.0.1 #Redis服务器连接端口 spring.redis.port=6379 #Redis服务器连接密码(默认为空) spring.redis.password= #连接池最大连接数(使用负值表示没有限制) spring.redis.jedis.pool.max-active=500 spring.redis.jedis.pool.max-idle=1000 spring.redis.jedis.pool.max-wait=6000ms spring.redis.jedis.pool.min-idle=4 #连接超时时间(毫秒) spring.redis.timeout=30000 # redisson lock redisson.address=redis://127.0.0.1:6379 redisson.password= 复制代码
3.新建redisson 配置类
import org.redisson.Redisson; import org.redisson.api.RedissonClient; import org.redisson.config.Config; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; /** * redisson 配置类 * Created on 2018/6/19 */ @Configuration public class RedissonConfig { @Value("${spring.redis.host}") private String host; @Value("${spring.redis.port}") private String port; @Value("${spring.redis.password}") private String password; @Bean public RedissonClient getRedisson(){ Config config = new Config(); config.useSingleServer().setAddress("redis://" + host + ":" + port) //心跳检测,定时与redis连接,可以防止一段时间过后,与redis的连接断开 .setPingConnectionInterval(1000) ; //添加主从配置 // config.useMasterSlaveServers().setMasterAddress("").setPassword("").addSlaveAddress(new String[]{"",""}); return Redisson.create(config); } } 复制代码
4.测试类
import com.zhipeng.testspringboot.redission.RedissonService; import org.redisson.api.RLock; import java.util.concurrent.TimeUnit; public class TestIt { static int number =0 ; public static int testredis(RedissonService redissonService){ RLock lock =null; try { lock = redissonService.getRLock("record2Ids"); if (!lock.isLocked()){ lock.lock(30, TimeUnit.MINUTES); number++; System.out.println(Thread.currentThread().getName()+"->:"+number); return 1; }else{ System.err.println(Thread.currentThread().getName() +"->:"+"被锁住了"); return 0; } }finally { if (null != lock && lock.isLocked() && lock.isHeldByCurrentThread()){ lock.unlock(); } } } } 复制代码
多线程调用此方法时,出现一个异常
问题描述
当我们使用Ression中Lock.lock()方法之后,如果存在线程并发常见情况下,会出现如下异常: java.lang.IllegalMonitorStateException: attempt to unlock lock, not locked by current thread by node id: 9f178836-f7e1-44fe-a89d-2db52f399c0d thread-id: 22
问题分析 在thread-1还没有结束的时候,也就是在thread-1在获得锁但是还没有释放锁的时候, `thread-2进入了try代码块内,获取不到锁后退出,进入了finally代码块,并且将thread-1的锁尝试解锁。所以thread-2并没有获得锁,还尝试去释放锁导致的。
问题解决
在finally里面添加判断 lock.isHeldByCurrentThread()
// 是当前执行线程的锁 if (lock.isHeldByCurrentThread()){ } 复制代码
同样的解决方法,可以解决当前方法执行超时后,锁自动释放,又在finally自动释放导致的问题。
作者:普金在中东散步
链接:https://juejin.cn/post/6992514166376382471