栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

使用redis实现分布式锁原理代码浅析

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

使用redis实现分布式锁原理代码浅析

  1. 实现原理是什么?
    获取锁时,判断该key是否存在,存在的话证明已被使用,则阻塞。所以采用setnx命令来操作,即不存在则插入,返回0证明已存在,返回1证明不存在且写入成功,我们规定,返回1则获取锁成功,进行相应的操作和返回。
  2. 为什么要设置超时时间?
    若是不设置超时时间,在unlock执行之前锁的系统挂掉,则此锁一直处于占用状态
  3. 若是业务处理时间大于设置的超时时间怎么办?
    所以需要使用子线程来更新超时时间
代码理解
import redis.clients.jedis.Jedis;


public class RedisLock {
    private final Jedis jedis;
    private final int timeExpired;
    private boolean shouldRenew = true;
    private long lastTime;

    public RedisLock(String ip) {
    	//有密码的自己单独修改
        jedis = new Jedis(ip.split(":")[0], 6379);
        timeExpired = 20;
    }

    public RedisLock(String ip, int timeExpired) {
        jedis = new Jedis(ip.split(":")[0], 6379);
        this.timeExpired = timeExpired;
    }

    public void getLock() {
        while (true) {
            Long setState = jedis.setnx("locks", "");
            if (setState == 1L) {
                //设置过期时间
                jedis.expire("locks", timeExpired);
                lastTime = System.currentTimeMillis();
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        while (shouldRenew) {
                            final long nowTime = System.currentTimeMillis();
                            if (nowTime - lastTime > timeExpired / 3 * 1000) {
                                //子线程重置超时时间, 防止超时时间过去了,锁的业务还没处理完毕
                                lastTime = nowTime;
                                jedis.expire("locks", timeExpired);
                            }
                            try {
                                Thread.sleep(100);
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                        }
                    }
                }).start();
                return;
            }
        }
    }

    public void unLock() {
        //思考: 先置为false 还是 先del? 二者有区别吗
        shouldRenew = false;
        jedis.del("locks");
    }
}

测试代码
public class LockTest {
    public static void main(String[] args) throws InterruptedException {
        final RedisLock locks1 = new RedisLock("127.0.0.1");
        final RedisLock locks2 = new RedisLock("127.0.0.1");
        System.out.println("连接完毕");
        new Thread(() -> {
            try {
                locks1.getLock();
                System.out.println("线程1获取到锁");
                Thread.sleep(30000);
                System.out.println("线程1释放锁");
                locks1.unLock();
            } catch (Exception e) {
            }
        }).start();

        new Thread(() -> {
            try {
                locks2.getLock();
                System.out.println("线程2获取到锁");
                Thread.sleep(30000);
                System.out.println("线程2释放锁");
                locks2.unLock();
            } catch (Exception e) {
            }
        }).start();
        Thread.sleep(1000000000);
    }
}

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/282106.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号