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,正确,没超卖

.net Redis分布式锁,Dictionary,ConcurrentDictionary 介绍的更多相关文章

  1. 分布式-技术专区-Redis分布式锁实现-第一步

    承接前面一篇Redis分布式锁的原理介绍 https://www.cnblogs.com/liboware/p/11921759.html 我们针对于实现方案进行接下来上篇进行重新的规划和定义以及完善 ...

  2. Redis分布式锁 (图解-秒懂-史上最全)

    文章很长,而且持续更新,建议收藏起来,慢慢读! 高并发 发烧友社群:疯狂创客圈(总入口) 奉上以下珍贵的学习资源: 疯狂创客圈 经典图书 : 极致经典 + 社群大片好评 < Java 高并发 三 ...

  3. 死磕 java同步系列之redis分布式锁进化史

    问题 (1)redis如何实现分布式锁? (2)redis分布式锁有哪些优点? (3)redis分布式锁有哪些缺点? (4)redis实现分布式锁有没有现成的轮子可以使用? 简介 Redis(全称:R ...

  4. redis咋么实现分布式锁,redis分布式锁的实现方式,redis做分布式锁 积极正义的少年

    前言 分布式锁一般有三种实现方式:1. 数据库乐观锁:2. 基于Redis的分布式锁:3. 基于ZooKeeper的分布式锁.本篇博客将介绍第二种方式,基于Redis实现分布式锁.虽然网上已经有各种介 ...

  5. spring boot redis分布式锁

    随着现在分布式架构越来越盛行,在很多场景下需要使用到分布式锁.分布式锁的实现有很多种,比如基于数据库. zookeeper 等,本文主要介绍使用 Redis 做分布式锁的方式,并封装成spring b ...

  6. Redis分布式锁的正确实现方式

    前言 分布式锁一般有三种实现方式:1. 数据库乐观锁:2. 基于Redis的分布式锁:3. 基于ZooKeeper的分布式锁.本篇博客将介绍第二种方式,基于Redis实现分布式锁.虽然网上已经有各种介 ...

  7. Redis分布式锁---完美实现

    这几天在做项目缓存时候,因为是分布式的所以需要加锁,就用到了Redis锁,正好从网上发现两篇非常棒的文章,来和大家分享一下. 第一篇是简单完美的实现,第二篇是用到的Redisson. Redis分布式 ...

  8. 关于分布式锁原理的一些学习与思考-redis分布式锁,zookeeper分布式锁

    首先分布式锁和我们平常讲到的锁原理基本一样,目的就是确保,在多个线程并发时,只有一个线程在同一刻操作这个业务或者说方法.变量. 在一个进程中,也就是一个jvm 或者说应用中,我们很容易去处理控制,在j ...

  9. 【分布式缓存系列】集群环境下Redis分布式锁的正确姿势

    一.前言 在上一篇文章中,已经介绍了基于Redis实现分布式锁的正确姿势,但是上篇文章存在一定的缺陷——它加锁只作用在一个Redis节点上,如果通过sentinel保证高可用,如果master节点由于 ...

随机推荐

  1. OpenGL入门(一):使用GLFW创建简单的窗口

    如果使用QT,那么创建一个OpenGL渲染窗口其实很容易,不过出于初学的角度,使用GLFW库来创建新窗口. 1. 下载并配置GLFW GLFW是一个专门针对OpenGL的C语言库,它提供了一些渲染物体 ...

  2. html5 localStorage讲解

    早期的web中使用cookies在客户端保存诸如用户名等简单的信息,但是,在使用cookies存储永久数据存在以下问题. 1.cookies的大小限制在4kB,不适合大量的数据存储. 2.浏览器还限制 ...

  3. python中判断两个对象是否相等

    #coding=utf-8#比较两个对象是否相等#python 2中使用cmp(),==,is#is 主要是判断 2 个变量是否引用的是同一个对象,如果是的话,则返回 true,否则返回 false. ...

  4. day22_7.26面向对象之封装(接口与抽象)

    一.封装. 封装就是将丑陋复杂的隐式的细节隐藏到内部,对外提供简单的使用接口. 对外隐藏内部实现细节,并提供访问的接口.对内使用self操作. 二.为什么要封装? 对于一个计算机来说,不可能不使用机箱 ...

  5. reactjs中配置代理跨域

    第一步,下载依赖 http-proxy-middleware yarn add http-proxy-middleware 第二步,在src下建立setupProxy.js const proxy = ...

  6. bootstrap-table 列拖动

    1.页面js/css <!-- bootstrap 插件样式 --> <link th:href="@{/common/bootstrap-3.3.6/css/bootst ...

  7. [LeetCode] 327. Count of Range Sum 区间和计数

    Given an integer array nums, return the number of range sums that lie in [lower, upper] inclusive.Ra ...

  8. 【贪心】umi的函数

    原题传送门 思路 这道题乍一看很难,然而实际在草纸上一模拟,结果就出来了. 分析:这道题实际上要么无解,要么有无数个解,因而题目只要求输出了一个解(明白这点题目就做出来一半了). 题中,规定所求z满足 ...

  9. 关于Dev-C++用户所必须知道的知识

    开启这几个警告选项,才能拥有GCC编译器的较为全面的报错和警告 另外,目前Dev-C早已停止更新(停滞在版本号5.1,内置的GCC为4.9版本),且使用其检测数组变量也挺麻烦的,实在不推荐使用.

  10. MySQL的SQL语句——常见报错

    Eclipse连接MySQL数据库 — 8.0版jdbc驱动 键知识 https://blog.csdn.net/jenminzhang/article/details/9816853 [必应翻译] ...