zoukankan      html  css  js  c++  java
  • .net Redis分布式锁,Dictionary,ConcurrentDictionary 介绍

    1、背景

    在计算机世界里,对于锁大家并不陌生,在现代所有的语言中几乎都提供了语言级别锁的实现,为什么我们的程序有时候会这么依赖锁呢?这个问题还是要从计算机的发展说起,随着计算机硬件的不断升级,多核cpu,多线程,多通道等技术把计算机的计算速度大幅度提升,原来同一时间只能执行一条cpu指令的时代已经过去。随着多条cpu指令可以并行执行的原因,原来不曾出现的资源竞争随着出现,在程序中的体现就是随处可见的多线程环境。比如要更新数据库的一个信息,如果没有并发控制,多个线程同时操作的话,就会出现互相覆盖的现象发生。

    锁要解决的就是资源竞争的问题,也就是要把执行的指令顺序化。

    在互联网背景下,电商行业是普遍都是多线程执行,并发量大。比如下单秒杀抢购商品活动,属于高并发情况,库存的保证就尤其重要了,不能出现超卖现象。程序员所要做的事情就是需要单线程执行获取库存,再减库存操作,保证数据原子性。

    在多台服务器中,锁就是重点。

    2、应用

    我们先来介绍下单线程下的情况,假设有个商品A,库存500件,假设每次购买1件,单价1元,这样就只有是500次下单时成功的,其他都不能下单。

    2.1  Store商品存储-Dictionary

    数据库不存在的情况下,用Dictionary来代替

     创建了Store后,主程序创建下单,单线程执行。

     执行结果:

     执行正常,4人不能下单。

    改成多线程执行,直接出现超卖现象,其中用Task.Run 模拟多线程,其中Order(int i) i变量注意,不能直接填写i,异步中上下文不存在,因为主线程以及跑完了,再运行异步Task线程,这时变量已是最后一个被覆盖。

    解决方案是重复赋值变量替换

     结果:

     500多的人都买了。

    解决方案:

    2.1.1  lock 加锁

    lock很明显影响性能。

     

     执行结果:

     正常。

    2.1.2  使用ConcurrentDictionary

    ConcurrentDictionary 本身是线程安全的,源代码就是加了lock

     

     

     执行结果符合。

    2.2 用Redis分布式锁

    redis是单线程运行,所以适合。原理也很简单,运用redis以下指令

    1、SETNX
    SETNX key val:当且仅当key不存在时,set一个key为val的字符串,返回1;若key存在,则什么都不做,返回0。
    2、expire
    expire key timeout:为key设置一个超时时间,单位为second,超过这个时间锁会自动释放,避免死锁。
    3、delete
    delete key:删除key
    在使用Redis实现分布式锁的时候,主要就会使用到这三个命令。

    原理如下:

    1、先获取redis锁,设置一个随机字符串

     

     

     执行了805次,看下输出最后数量有没有小于0

     结果显示0,正确,没超卖

  • 相关阅读:
    2.Spring Boot 有哪些优点?
    3.什么是 JavaConfig?
    4.如何重新加载 Spring Boot 上的更改,而无需重新启动服务器?
    Java中的异常处理机制的简单原理和应用。
    垃圾回收的优点和原理。并考虑2种回收机制。
    我们在web应用开发过程中经常遇到输出某种编码的字符,如iso8859-1等,如何输出一个某种编码的字符串?
    Request对象的主要方法:
    JSP的内置对象及方法。
    Servlet执行时一般实现哪几个方法?
    说说你所熟悉或听说过的j2ee中的几种常用模式?及对设计模式的一些看法
  • 原文地址:https://www.cnblogs.com/zjtao/p/11451806.html
Copyright © 2011-2022 走看看