明霞山资源网 Design By www.htccd.com

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这个性质,可以实现分布式锁,当然设计一定复杂一些!

总结

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

标签:
redis锁机制,redis锁机制介绍,redis锁机制实例

明霞山资源网 Design By www.htccd.com
广告合作:本站广告合作请联系QQ:858582 申请时备注:广告合作(否则不回)
免责声明:本站文章均来自网站采集或用户投稿,网站不提供任何软件下载或自行开发的软件! 如有用户或公司发现本站内容信息存在侵权行为,请邮件告知! 858582#qq.com
明霞山资源网 Design By www.htccd.com

《魔兽世界》大逃杀!60人新游玩模式《强袭风暴》3月21日上线

暴雪近日发布了《魔兽世界》10.2.6 更新内容,新游玩模式《强袭风暴》即将于3月21 日在亚服上线,届时玩家将前往阿拉希高地展开一场 60 人大逃杀对战。

艾泽拉斯的冒险者已经征服了艾泽拉斯的大地及遥远的彼岸。他们在对抗世界上最致命的敌人时展现出过人的手腕,并且成功阻止终结宇宙等级的威胁。当他们在为即将于《魔兽世界》资料片《地心之战》中来袭的萨拉塔斯势力做战斗准备时,他们还需要在熟悉的阿拉希高地面对一个全新的敌人──那就是彼此。在《巨龙崛起》10.2.6 更新的《强袭风暴》中,玩家将会进入一个全新的海盗主题大逃杀式限时活动,其中包含极高的风险和史诗级的奖励。

《强袭风暴》不是普通的战场,作为一个独立于主游戏之外的活动,玩家可以用大逃杀的风格来体验《魔兽世界》,不分职业、不分装备(除了你在赛局中捡到的),光是技巧和战略的强弱之分就能决定出谁才是能坚持到最后的赢家。本次活动将会开放单人和双人模式,玩家在加入海盗主题的预赛大厅区域前,可以从强袭风暴角色画面新增好友。游玩游戏将可以累计名望轨迹,《巨龙崛起》和《魔兽世界:巫妖王之怒 经典版》的玩家都可以获得奖励。