• redis锁机制介绍与实例


    转自:https://m.jb51.net/article/154421.htm

    今天小编就为大家分享一篇关于redis锁机制介绍与实例,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧

    1 悲观锁

    执行操作前假设当前的操作肯定(或有很大几率)会被打断(悲观)。基于这个假设,我们在做操作前就会把相关资源锁定,不允许自己执行期间有其他操作干扰。

    Redis不支持悲观锁。Redis作为缓存服务器使用时,以读操作为主,很少写操作,相应的操作被打断的几率较少。不采用悲观锁是为了防止降低性能。

    2 乐观锁

    执行操作前假设当前操作不会被打断(乐观)。基于这个假设,我们在做操作前不会锁定资源,万一发生了其他操作的干扰,那么本次操作将被放弃。

    3. Redis中的锁策略

    Redis采用了乐观锁策略(通过watch操作)。乐观锁支持读操作,适用于多读少写的情况!
    在事务中,可以通过watch命令来加锁;使用 UNWATCH可以取消加锁;
    如果在事务之前,执行了WATCH(加锁),那么执行EXEC 命令或 DISCARD 命令后,锁对自动释放,即不需要再执行 UNWATCH 了

    例子

    redis锁工具类

    package com.fly.lock;
    import redis.clients.jedis.Jedis;
    import redis.clients.jedis.JedisPool;
    import redis.clients.jedis.JedisPoolConfig;
    public class RedisLock {
      //初始化redis池
      private static JedisPoolConfig config;
      private static JedisPool pool;
      static {
        config = new JedisPoolConfig();
        config.setMaxTotal(30);
        config.setMaxIdle(10);
        pool = new JedisPool(config, "192.168.233.200", 6379);
      }
      /**
       * 给target上锁
       * @param target
       **/
      public static void lock(Object target) {
        //获取jedis
        Jedis jedis = pool.getResource();
        //result接收setnx的返回值,初始值为0
        Long result= 0L;
        while (result < 1) {
          //如果target在redis中已经存在,则返回0;否则,在redis中设置target键值对,并返回1
          result = jedis.setnx(target.getClass().getName() + target.hashCode(), Thread.currentThread().getName());
        }
        jedis.close();
      }
      /**
       * 给target解锁
       * @param target
       **/
      public static void unLock(Object target) {
        Jedis jedis = pool.getResource();
        //删除redis中target对象的键值对
        Long del = jedis.del(target.getClass().getName() + target.hashCode());
        jedis.close();
      }
      /**
       * 尝试给target上锁,如果锁成功返回true,如果锁失败返回false
       * @param target
       * @return
       **/
      public static boolean tryLock(Object target) {
        Jedis jedis = pool.getResource();
        Long row = jedis.setnx(target.getClass().getName() + target.hashCode(), "true");
        jedis.close();
        if (row > 0) {
          return true;
        }
        return false;
      }
    }

    测试类

    package com.fly.test;
    import com.fly.lock.RedisLock;
    class Task {
      public void doTask() {
        //上锁
        RedisLock.lock(this);
        System.out.println("当前线程: " + Thread.currentThread().getName());
        System.out.println("开始执行: " + this.hashCode());
        try {
          System.out.println("doing...");
          Thread.sleep(2000);
        } catch (InterruptedException e) {
          e.printStackTrace();
        }
        System.out.println("完成: " + this.hashCode());
        //解锁
        RedisLock.unLock(this);
      }
    }
    public class Demo {
      public static void main(String[] args) {
        Task task = new Task();
        Thread[] threads = new Thread[5];
        for (Thread thread : threads) {
          thread = new Thread(()->{
            task.doTask();
          });
          thread.start();
        }
      }
    }

    输出结果:

    ----------------------------------------------
    当前线程: Thread-0
    开始执行: 2081499965
    doing...
    完成: 2081499965
    ----------------------------------------------
    当前线程: Thread-2
    开始执行: 2081499965
    doing...
    完成: 2081499965
    ----------------------------------------------
    当前线程: Thread-1
    开始执行: 2081499965
    doing...
    完成: 2081499965
    ----------------------------------------------
    当前线程: Thread-4
    开始执行: 2081499965
    doing...
    完成: 2081499965
    ----------------------------------------------
    当前线程: Thread-3
    开始执行: 2081499965
    doing...
    完成: 2081499965

    去掉redis锁后,执行结果:

    ----------------------------------------------
    ----------------------------------------------
    当前线程: Thread-2
    开始执行: 1926683415
    ----------------------------------------------
    当前线程: Thread-1
    doing...
    当前线程: Thread-0
    ----------------------------------------------
    当前线程: Thread-3
    开始执行: 1926683415
    doing...
    开始执行: 1926683415
    doing...
    ----------------------------------------------
    开始执行: 1926683415
    doing...
    当前线程: Thread-4
    开始执行: 1926683415
    doing...
    完成: 1926683415
    完成: 1926683415
    完成: 1926683415
    完成: 1926683415
    完成: 1926683415

    Process finished with exit code 0

    利用redis这个性质,可以实现分布式锁,当然设计一定复杂一些!

    总结

    以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对脚本之家的支持。如果你想了解更多相关内容请查看下面相关链接

  • 相关阅读:
    [转]学习B站动态转发抽奖脚本
    【LeetCode】236. 二叉树的最近公共祖先
    Java中邮件的发送
    最长递增子序列(LIS)
    最长公共子序列(LCS)
    【LeetCode】69. x 的平方根
    Lombok的使用
    Centos 中文乱码解决方法
    FWT,FST入门
    [UOJ310][UNR #2]黎明前的巧克力
  • 原文地址:https://www.cnblogs.com/sharpest/p/10788160.html
Copyright © 2020-2023  润新知