单机redisson使用redis锁,遇到的问题记录

1,655 阅读1分钟

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自动释放导致的问题。