欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

redis锁机制介绍与实例

程序员文章站 2022-04-16 14:41:16
1 悲观锁 执行操作前假设当前的操作肯定(或有很大几率)会被打断(悲观)。基于这个假设,我们在做操作前就会把相关资源锁定,不允许自己执行期间有其他操作干扰。 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这个性质,可以实现分布式锁,当然设计一定复杂一些!

总结

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