当前位置:首页 » 编程软件 » 脚本重入

脚本重入

发布时间: 2023-05-28 01:17:20

A. 大厂面试题详解:如何用Redis实现分布式锁

说一道常见面试题:

一个很简单的答案就是去使用 Redission 客户端。Redission 中的锁方案就是 Redis 分布式锁得比较完美的详细方案。

那么,Redission 中的锁方案为什么会比较完美呢?

正好,我用 Redis 做分布式锁经验十分丰富,在实际工作中,也 探索 过许多种使用 Redis 做分布式锁的方案,经过了无数血泪教训。

所以,在谈及 Redission 锁为什么比较完美之前,先给大家看看我曾经使用 Redis 做分布式锁是遇到过的问题。

我曾经用 Redis 做分布式锁是想去解决一个用户抢优惠券的问题。这个业务需求是这样的:当用户领完一张优惠券后,优惠券的数量必须相应减一,如果优惠券抢光了,就不允许用户再抢了。

在实现时,先从数据库中先读出优惠券的数量进行判断,当优惠券大于 0,就进行允许领取优惠券,然后,再将优惠券数量减一后,写回数据库。

当时由于请求数量比较多,所以,我们使用了三台服务器去做分流。

这个时候会出现一个问题:

如果其中一台服务器上的 A 应用获取到了优惠券的数量之后,由于处理相关业务逻辑,未及时更新数据库的优惠券数量;在 A 应用处理业务逻辑的时候,另一台服务器上的 B 应用更新了优惠券数量。那么,等 A 应用去更新数据库中优惠券数量时,就会把 B 应用更新的优惠券数量覆盖掉。

看到这里,可能有人比较奇怪,为什么这里不直接使用 SQL:

原因是这样做,在没有分布式锁的协调下,优惠券数量可能直接会出现负数。因为当前优惠券数量为 1 的时候,如果两个用户通过两台服务器同时发起抢优惠券的请求,都满足优惠券大于 0 每个条件,然后都执行这条 SQL 说了句,结果优惠券数量直接变成 -1 了。

还有人说可以用乐观锁,比如使用如下 SQL:

这种方式就在一定几率下,很可能出现数据一直更新不上,导致长时间重试的情况。

所以,经过综合考虑,我们就采用了 Redis 分布式锁,通过互斥的方式,以防止多个客户端同时更新优惠券数量的方案。

当时,我们首先想到的就是使用 Redis 的 setnx 命令,setnx 命令其实就是 set if not exists 的简写。告则

当 key 设置值成功后,则返回 1,否则就返回 0。所以,这里 setnx 设置成功可以表示成获取到锁,如果失败,则说明已经有锁,可以被视作获取锁失败。

如果想要释放锁,执行任务 del 指令,把 key 删除即可。

利用这个特性,我们就可以让系统在返毁执行优惠券逻辑之前,先去 Redis 中执行 setnx 指令。再根漏友备据指令执行结果,去判断是否获取到锁。如果获取到了,就继续执行业务,执行完再使用 del 指令去释放锁。如果没有获取到,就等待一定时间,重新再去获取锁。

乍一看,这一切没什么问题,使用 setnx 指令确实起到了想要的互斥效果。

但是,这是建立在所有运行环境都是正常的情况下的。一旦运行环境出现了异常,问题就出现了。

想一下,持有锁的应用突然崩溃了,或者所在的服务器宕机了,会出现什么情况?

这会造成死锁——持有锁的应用无法释放锁,其他应用根本也没有机会再去获取锁了。这会造成巨大的线上事故,我们要改进方案,解决这个问题。

怎么解决呢?咱们可以看到,造成死锁的根源是,一旦持有锁的应用出现问题,就不会去释放锁。从这个方向思考,可以在 Redis 上给 key 一个过期时间。

这样的话,即使出现问题,key 也会在一段时间后释放,是不是就解决了这个问题呢?实际上,大家也确实是这么做的。

不过,由于 setnx 这个指令本身无法设置超时时间,所以一般会采用两种办法来做这件事:

1、采用 lua 脚本,在使用 setnx 指令之后,再使用 expire 命令去给 key 设置过期时间。

2、直接使用 set(key,value,NX,EX,timeout) 指令,同时设置锁和超时时间。

以上两种方法,使用哪种方式都可以。

释放锁的脚本两种方式都一样,直接调用 Redis 的 del 指令即可。

到目前为止,我们的锁既起到了互斥效果,又不会因为某些持有锁的系统出现问题,导致死锁了。这样就完美了吗?

假设有这样一种情况,如果一个持有锁的应用,其持有的时间超过了我们设定的超时时间会怎样呢?会出现两种情况:

出现第一种情况比较正常。因为你毕竟执行任务超时了,key 被正常清除也是符合逻辑的。

但是最可怕的是第二种情况,发现设置的 key 还存在。这说明什么?说明当前存在的 key,是另外的应用设置的。

这时候如果持有锁超时的应用调用 del 指令去删除锁时,就会把别人设置的锁误删除,这会直接导致系统业务出现问题。

所以,为了解决这个问题,我们需要继续对 Redis 脚本进行改动……毁灭吧,累了……

首先,我们要让应用在获取锁的时候,去设置一个只有应用自己知道的独一无二的值。

通过这个唯一值,系统在释放锁的时候,就能识别出这锁是不是自己设置的。如果是自己设置的,就释放锁,也就是删除 key;如果不是,则什么都不做。

脚本如下:

或者

这里,ARGV[1] 是一个可传入的参数变量,可以传入唯一值。比如一个只有自己知道的 UUID 的值,或者通过雪球算法,生成只有自己持有的唯一 ID。

释放锁的脚本改成这样:

可以看到,从业务角度,无论如何,我们的分布式锁已经可以满足真正的业务需求了。能互斥,不死锁,不会误删除别人的锁,只有自己上的锁,自己可以释放。

一切都是那么美好!!!

可惜,还有个隐患,我们并未排除。这个隐患就是 Redis 自身。

要知道,lua 脚本都是用在 Redis 的单例上的。一旦 Redis 本身出现了问题,我们的分布式锁就没法用了,分布式锁没法用,对业务的正常运行会造成重大影响,这是我们无法接受的。

所以,我们需要把 Redis 搞成高可用的。一般来讲,解决 Redis 高可用的问题,都是使用主从集群。

但是搞主从集群,又会引入新的问题。主要问题在于,Redis 的主从数据同步有延迟。这种延迟会产生一个边界条件:当主机上的 Redis 已经被人建好了锁,但是锁数据还未同步到从机时,主机宕了。随后,从机提升为主机,此时从机上是没有以前主机设置好的锁数据的——锁丢了……丢了……了……

到这里,终于可以介绍 Redission(开源 Redis 客户端)了,我们来看看它怎么是实现 Redis 分布式锁的。

Redission 实现分布式锁的思想很简单,无论是主从集群还是 Redis Cluster 集群,它会对集群中的每个 Redis,挨个去执行设置 Redis 锁的脚本,也就是集群中的每个 Redis 都会包含设置好的锁数据。

我们通过一个例子来介绍一下。

假设 Redis 集群有 5 台机器,同时根据评估,锁的超时时间设置成 10 秒比较合适。

第 1 步,咱们先算出集群总的等待时间,集群总的等待时间是 5 秒(锁的超时时间 10 秒 / 2)。

第 2 步,用 5 秒除以 5 台机器数量,结果是 1 秒。这个 1 秒是连接每台 Redis 可接受的等待时间。

第 3 步,依次连接 5 台 Redis,并执行 lua 脚本设置锁,然后再做判断:

再额外多说一句,在很多业务逻辑里,其实对锁的超时时间是没有需求的。

比如,凌晨批量执行处理的任务,可能需要分布式锁保证任务不会被重复执行。此时,任务要执行多长时间是不明确的。如果设置分布式锁的超时时间在这里,并没有太大意义。但是,不设置超时时间,又会引发死锁问题。

所以,解决这种问题的通用办法是,每个持有锁的客户端都启动一个后台线程,通过执行特定的 lua 脚本,去不断地刷新 Redis 中的 key 超时时间,使得在任务执行完成前,key 不会被清除掉。

脚本如下:

其中,ARGV[1] 是可传入的参数变量,表示持有锁的系统的唯一值,也就是只有持有锁的客户端才能刷新 key 的超时时间。

到此为止,一个完整的分布式锁才算实现完毕。总结实现方案如下:

这个分布式锁满足如下四个条件:

当然,在 Redission 中的脚本,为了保证锁的可重入,又对 lua 脚本做了一定的修改,现在把完整的 lua 脚本贴在下面。

获取锁的 lua 脚本:

对应的刷新锁超时时间的脚本:

对应的释放锁的脚本:

到现在为止,使用 Redis 作为分布式锁的详细方案就写完了。

我既写了一步一坑的坎坷经历,也写明了各个问题和解决问题的细节,希望大家看完能有所收获。

最后再给大家提个醒,使用 Redis 集群做分布式锁,有一定的争议性,还需要大家在实际用的时候,根据现实情况,做出更好的选择和取舍。

原文 https://www.cnblogs.com/siyuanwai/p/16011836.html

B. 网页打印时出来脚本错误,求高手帮忙解决~~谢谢

无效过程调用或参数
在过程调用中传递了一个无效参数。这可能是由于参数超出范围,或包含无效数据。另外,有可能在蠢冲不适当的时间对过程进行了调用。
要纠正该错误
验证传递给过程的参数是有效的。
验证在适当的时间调用函数。
溢出
试图赋给变量的赋值太大,这是因为:
赋值,计算或者数据类型转换结果很大以至于不能代表此种类型变量值的范围。
属性赋值超出了属性所能接受的最大值。
整数类型数字圆手的计算结果大于一个整数。
要纠正该错误
将值赋给一个较大取值范围的变量类型。
确保赋值符合属性范围。
内存不足
分配与该计算机有效内存一样多的内存。这可能是一个动态分配数组增长得带腔歼太大,或者是对象实例数目过多。
要纠正该错误
使用Erase语句来重新分配动态数组的储存空间。
使用ReDim语句来重新分配储存空间。
关闭任何已经打开、不必需的应用程序,文件或者源文件。
下标越界
访问的数组中元素数目比期望的少。例如试图从一个定义为10个元素的数组中访问到11个元素。.
要纠正该错误
确保你的代码中包含检察元素是否越界的边界。
重新定义一个更大的数组大小至需要的维数。
该数组为定长的或者临时被锁定
试图用 ReDim 函数来改变一个定长数组的元素数目。动态数组或者 Variant 变量内的数组可以被暂时的锁定。
要纠正该错误
如果在过程内部定义数组,用 ReDim 函数将其从静态变为动态。
如果在模块水平上说明数组,不要指定数组中元素的数目。
被零除
创建一个试图将数字被零除的表达式。被零除得到无穷大(不可用)结果。
要纠正该错误
检查表达式的输入或大小写错误。
类型不匹配
试图比较不相容数据类型的值。例如,比较一个字符串和一个数值。
要纠正该错误
当进行比较时,要确保数据类型相同。
用一个的数据类型来计算另一个的值,然后重新比较。
字符串空间溢出
试图创建字符串对象时系统内存被用尽。这可能是因为动态分配数组越来越大或对象实例的数目过大。
要纠正该错误
使用 Erase 语句来重新分配动态数组的储存空间。
使用 ReDim 语句来重新分配储存空间。
关闭任何已经打开、不必需的应用程序,文件或者源文件
无法执行请求的操作
当主机使脚本引擎中断时无法继续执行脚本。主机未指定明确的返回错误代码。
要纠正该错误
该错误的解决与主机有关。
堆栈溢出
过程嵌套太深。每次代码从一个过程跳到另一个过程,本地变量的内容被放到堆栈中。堆栈是一个大小随着要求执行的脚本动态增长和缩小的内存工作区域。
要纠正该错误
检查没有嵌套很深的过程。
确保递归(重入)过程没有经常的调用自身。
确保递归过程被正常终止。
未定义 Sub 或 Function
试图调用一个不存在的过程。
要纠正该错误
检查过程的拼写确保输入正确。
加载 DLL 错误
应用程序引用了一个无法找到的DLL,一个DLL可能引用了另一个无法找到的DLL。
要纠正该错误
确保DLL存在。
使用全路径名引用DLL。
获得被引用的DLL并使其对其他DLL有效。
内部错误
发生内部错误。
要纠正该错误
除非这是由Raise 方法产生,请与微软产品服务联系报告出现错误消息的情况。
未设置对象变量
试图使用无效对象的对象属性。如果遗漏了 Set语句,将在对象引用产生错误。
要纠正该错误
为对象变量指定一个引用。
For 循环未初始化
在脚本中执行跳到For...Next 循环中间的结果。由于For...Next 循环计数必须被初始化所以产生错误。下面演示了一个For...Next 循环的正确结构。
For counter = start To end [Step step] [statements] [Exit For] [statements] Next
要纠正该错误
移去跳转至For...Next 循环的语句。
确保For...Next循环包含了所有必须的部分。
非法使用 Null
试图获得一个为Null 的Variant变量的值。你只能获得包含有效值的Variant 变量的值。Null 是一个 Variant 一个用来指示一个数据项不包含任何有效数据的子类型。
要纠正该错误
确保变量包含有效数据。
需要对象
提供的对象无效(或无法认为是一个对象)。对属性和方法的引用需要一个显式的对象限定符。
要纠正该错误
提供一个对象限定符。
检查对象限定符的拼写。
ActiveX 部件无法创建对象
由于对象类未在系统注册表中注册或者是一个或多个相关的动态链接库无效(DLLs), VB 5.5运行时无法初始化对象。另外一种可能情况是,由于未找到或是已经损坏,对象所需的DLL不可用。
要纠正该错误
确保所有相关的DLLs有效。例如,数据存取对象(DAO)所需的DLLs在不同的平台下是不同的。你可能不得不返回到安装程序查找该对象。
Internet Explorer可能试图创建对象,但是在Internet Explorer中没有正确的安全许可。重置Internet Explorer 安全设置并重试。
类不支持自动化
试图操作一个并不支持自动化的对象属性或方法。可以创建并将指针传递给不支持自动化的对象,但是不能获取它的属性和方法。
要纠正该错误
查创建对象应用程序的文档中关于该类自动化使用的限制。
注意 对象可能已经通过使用CreateObject 被创建,但可能已经通过主机对象模型被引入。
在自动化操作中未找到文件名或类名
使用GetObject 函数,但是将一个不可识别的类或文件名作为参数。GetObject 函数要求包含要获取的对象的文件的完整的路径和名称,或者是在系统中注册过的类名称。
要纠正该错误
检查名称的拼写错误,然后重试。
确保class 参数的名称与在系统中注册的相匹配。
对象不支持该属性或方法
对该自动化对象指定了一个并不存在的属性或方法。不是所有的对象都支持所有的属性和方法。
要纠正该错误
检查属性和方法以确保没有打字错误。
参见对象的文档获取更多的信息。
对象不支持此操作
试图引用该对象不支持的一个方法或属性。不是所有的对象支持所用的操作。
要纠正该错误
检查属性和方法以确保没有打字错误。
参见对象的文档获取更多的信息。
对象不支持当前的区域设置
试图操作一个不支持当前区域设置的对象。区域设置是和给定语言以及国家/地区相对应的一系列信息。本地影响预定义程序项的语言和本地特定设置。以下两种情况时本地信息很重要:
code locale 影响语言项例如关键词,并且定义本地特定设置例如小数和列表分割符,日期格式和字符排列顺序。
system locale 影响本地相关的功能执行。例如,当显示数字或者将字符串转换为日期时。使用操作系统提供的控制面板工具来设定系统。
要纠正该错误
检查对象支持的区域设置。
未找到命名参数
调用一个过程并指定一个特别的参数,但是过程未被定义为接受以为名称的参数。除非在过程定义中出现,一个命名参数不能在过程调用中使用。
要纠正该错误
检查参数名称是否正确拼写,然后再试着调用过程。
参数不可选
调用过程但是参数数量错误。传递给过程的参数的数量必须与过程定义的参数数量相同。
要纠正该错误
检查函数符号确保提供了所有必须的参数。
错误的参数个数或无效的参数属性值
调用过程时如果:
错误的过程名称,
或者,
过程中参数数目错误,
或者,
参数类型错误。
传递给过程的参数数目必须与过程定义中的参数数目相符。
要纠正该错误
检查以确保传递给过程的参数列表与过程定义或声明中的相符。
对象不是一个集合
试图对一个不是 Collection 类型的对象进行只对 Collection 对象有效的操作。有些属性、方法和操作仅可应用于 Collection 对象。Collection 对象是包含一组互相关联的对象的一种对象。一旦集合中发生了改变,一个对象在 Collection 对象中的位置也会发生改变;因此,Collection 对象中的任何一个对象的位置都可能变化。
要纠正该错误
检查对象或属性名称的拼写。
验证对象是一个Collection 对象。
查看用来向集合中添加该对象的 Add 方法,确保语法正确且任何标识符的拼写都正确。
变量使用了 VB 不支持的自动化类型
试图使用类型库或者对象库中不被支持的数据类型,任何一门编程语言都不能使用类型库或对象库中的所有变量。
要纠正该错误
只使用VB识别的变量类型。
远程服务器不存在或者不能访问
用CreateObject函数 来建立一个远程机器的对象,但是调用失败,这是因为无法访问远程服务器或者没有包含特定的类。
要纠正该错误
检验远程服务器的名字是否正确。
检验远程服务器的 DCOM 可用。
使用 dcomcnfg 验证安全权限是否允许建立对象。
无效图片
试图加载一个无法识别格式的图像。有效格式包括位图(*.bmp),图标(*.ico),以及Windows 元文件(*.wmf)。
要纠正该错误
确保要加载的图像文件的格式是有效的。
变量未定义
在脚本开始处用Option Explicit 语句,后来又使用一个未被说明的变量名称。当使用Option Explicit 语句时,必须用Dim,Private,Public或者ReDim语句显式地说明所有的变量。
要纠正该错误
使用Option Explicit 语句时, 确保用Dim, Private, Public, Or ReDim语句定义了所有的变量。
脚本对象不安全
试图使用未被标识为脚本安全的对象。对象创建是否安全由主机决定。总的来说,允许不信任脚本进行有害操作(例如操作硬盘)的对象是不安全的。
例如,使用作为客户端的Microsoft Internet Explorer 运行 FileingObject 是不安全的,但是可以在带有Windows Host的本地机器使用该对象。
要纠正该错误
确保在使用一个安全的对象。
与对象开发者联系看是否为安全版本。
阅读对象文档发现该对象是否安全。
对象不能安全初始化
试图使用未被标识为初始化安全的对象。对象创建是否安全由主机决定。总的来说,允许不信任脚本进行有害操作(例如操作硬盘)的对象是不安全的。
例如,使用作为客户端的Microsoft Internet Explorer 运行 FileingObject 是不安全的,但是可以在带有Windows Host的本地机器使用该对象。
要纠正该错误
确保在使用一个安全的对象。
与对象开发者联系看是否为安全版本。
阅读对象文档发现该对象是否安全。
对象不能安全创建
试图使用一个未被标识为安全创建的对象。对象创建是否安全由主机决定。总的来说,允许不信任脚本进行有害操作(例如操作硬盘)的对象是不安全的。
例如,使用作为客户端的Microsoft Internet Explorer 运行 FileingObject 是不安全的,但是可以在带有Windows Host的本地机器使用该对象。
要纠正该错误
确保在使用一个安全的对象。
与对象开发者联系看是否为安全版本。
阅读对象文档发现该对象是否安全。
无效或不合格的引用
试图对不止一个对象使用With语句。With语句只能被非空对象使用。下面演示了一个With 块的正确结构。
With objectstatements End With
要纠正该错误
为With 语句指定一个对象。
类未定义
引用未定义(通过New 或 Set语句)的类。
要纠正该错误
确保在引用类之前已经定义。
发生异常
脚本调用COM对象,然后产生异常。
要纠正该错误
除非该调用由 Raise 方法产生,请与产生错误的CM对象开发人员联系。
请与微软产品服务联系报告出现错误消息的情况。
正则表达式中的语法错误
搜索字符串的结构违背了VB正则表达式中的一个或多个语法规则。
要纠正该错误
保证常规的搜索字符串的表达式符合Perlde的表达语法。
错误的数量词
当构造正则表达式的搜索模式时,没有正确的说明匹配的字符串。
要纠正该错误
确保搜索模式是正确构造的。
在正则表达式中需要 ']'
试图为正则表达式匹配创建一个字符类,但未包含右括号。将单独的字符组合放到方括号里可以将其装配到字符类中。例如, /[abc]/ 匹配字母“a”,“b”,或“c”中任意一个。
要纠正该错误
在正则表达式中添加右括号。
在正则表达式中需要 ')'
试图创建常规的嵌套表达式,但未包含“)”。在正则表达式中括号有几个目的。首先,它将分离的项组成为单个子表达式,所以项目可以通过*,+,?等等来当作一个单元来处理。
要纠正该错误
在常规的嵌套表达式中添加右(闭)括号“)”。
字符集越界
试图使用无效字符创建正则表达式。正则表达式是由字母数字和元字符组成的。
要纠正该错误
仅仅使用有效正则表达式字符来组成正则表达式。

C. 使用redis实现的分布式锁原理是什么

一、写在前面

现在面试,一般都会聊聊分布式系统这块的东西。通常面试官都会从服务框架(Spring Cloud、Dubbo)聊起,一路聊到分布式事务、分布式锁、ZooKeeper等知识。

所以咱们这篇文章就来聊聊分布式锁这块知识,具体的来看看Redis分布式锁的实现原理。

说实话,如果在公司里落地生产环境用分布式锁的时候,一定是会用开源类库的,比如Redis分布式锁,一般就是用Redisson框架就好了,非常的简便易用。

大家如果有兴趣,可以去看看Redisson的官网,看看如何在项目中引入Redisson的依赖,然后基于Redis实现分布式锁的加锁与释放锁。

下面给大家看一段简单的使用代码片段,先直观的感受一下:

大家看到了吧,那个myLock的hash数据结构中的那个客户端ID,就对应着加锁的次数

(5)释放锁机制

如果执行lock.unlock(),就可以释放分布式锁,此时的业务逻辑也是非常简单的。

其实说白了,就是每次都对myLock数据结构中的那个加锁次数减1。

如果发现加锁次数是0了,说明这个客户端已经不再持有锁了,此时就会用:

“del myLock”命令,从redis里删除这个key。

然后呢,另外的客户端2就可以尝试完成加锁了。

这就是所谓的分布式锁的开源Redisson框架的实现机制。

一般我们在生产系统中,可以用Redisson框架提供的这个类库来基于redis进行分布式锁的加锁与释放锁。

(6)上述Redis分布式锁的缺点

其实上面那种方案最大的问题,就是如果你对某个redis master实例,写入了myLock这种锁key的value,此时会异步复制给对应的master slave实例。

但是这个过程中一旦发生redis master宕机,主备切换,redis slave变为了redis master。

接着就会导致,客户端2来尝试加锁的时候,在新的redis master上完成了加锁,而客户端1也以为自己成功加了锁。

此时就会导致多个客户端对一个分布式锁完成了加锁。

这时系统在业务语义上一定会出现问题,导致各种脏数据的产生。

所以这个就是redis cluster,或者是redis master-slave架构的主从异步复制导致的redis分布式锁的最大缺陷:在redis master实例宕机的时候,可能导致多个客户端同时完成加锁。

D. Redis分布式锁的原理与面试细节

<meta name="source" content="lake">

这里就讲了下怎么加锁的,很多原理的问题小伙伴们,可用网络下分布式锁,看图中我特别在加锁与删除锁的时候还有俩个指向就特别说下这俩个问题

我们加锁的时候为了防止死锁的问题都在加锁散锋的时候会带上 锁过期时间的问题我们使用Redis提供的设置值的时候跟设置过期时间是原子性的操命令

加锁时候的原子性问题我们解决了,我们知道分布式锁就是只有一个线程才能抢到锁位,那其他线程怎么处理呢?有些文章可能都只说了一些流程却忘记了很多坑

加锁失败的几个解决办法【这也叫锁冲突的问题】

加锁过程我们处理好了,那么删除锁的时候呢?

删冲宴晌除锁的时候我们既要防止删除是别人锁有要当业务流程执行时间大于加锁的时间问题

删除锁的原子性就我们依靠了Lua脚本来实现删除锁的原子性

Redis锁超时问题呢?

使用过或者了解过Redisson的小伙伴知道Redisson框祥灶架实现分布式锁有一个看门狗机制,当业务流程大于加锁时间的时候,看门狗机制为在加锁的时间上在添加10秒

我们就来看看Redisson的加锁实现就可用到Redisson的看门狗机制跟分布式的可重入

【重点主要是依赖lua脚本的原子性,实现加锁和释放锁的功能】

使用redisson实现分布式锁的操作步骤,三部曲

第一步: 获取锁 RLock redissonLock = redisson.getLock(lockKey);

第二步: 加锁,实现锁续命功能 redissonLock.lock();

第三步:释放锁 redissonLock.unlock();

重点的地方我都标出来了

我们看下RedissonLock构造函数

参数:

继续看 lockInterruptibly方法

继续往里面追

大流程已经梳理完了,我们看下 Long ttl = tryAcquire(leaseTime, unit, threadId); 看门狗机制了

ARGV[2] ---------> getLockName(threadId) 实现如下

这个id就是自开始实例化RedissonLock的id ,是个UUID
我们来解释下这段lua脚本【讲的可重入逻辑】

那继续监听时间中的 scheleExpirationRenewal(threadId); 逻辑【看门狗续命】

重点看 unlockInnerAsync(Thread.currentThread().getId())

又是lua脚本,核心就是 把value减到为0 ,删除key

Redisson的逻辑参考

附上流程图

E. 急求《单片机C语言程序设计实训100例——基于8051+Proteus仿真》第三部分综合设计C语言源代码

这本书一共5章节,你说第三部分指的哪里?
第五章才是综合设计部分啊,而且这部分有好多例程,也不知道你要哪部分?
第1章 8051单片机C语言程序设计概述 1
1.1 8051单片机引脚 1
1.2 数据与程序内存 5
1.3 特殊功能寄存器 6
1.4 外部中断、定时器/计数器及串口应用 8
1.5 有符号与无符号数应用、数位分解、位操作 9
1.6 变量、存储类型与存储模式 11
1.7 关于C语言运算符的优先级 13
1.8 字符编码 15
1.9 数组、字符串与指针 16
1.10 流程控制 18
1.11 可重入函数和中断函数 19
1.12 C语言在单片机系统开发中的优势 20
第2章 Proteus操作基础 21
2.1 Proteus操作界面简介 21
2.2 仿真电路原理图设计 22
2.3 元件选择 25
2.4 调试仿真 29
2.5 Proteus与Vision 3的联合调试 29
2.6 Proteus在8051单片机应用系统开发的优势 30
第3章 基础程序设计 32
3.1 闪烁的LED 32
3.2 双向来回的流水灯 34
3.3 花样流水灯 36
3.4 LED模拟交通灯 38
3.5 分立式数码管循环显示0~9 40
3.6 集成式数码管动态扫描显示 41
3.7 按键调节数码管闪烁增减显示 44
3.8 数码管显示4×4键盘矩阵按键 46
3.9 普通开关与拨码开关应用 49
3.10 继电器及双向可控硅控制照明设备 51
3.11 INT0中断计数 53
3.12 INT0及INT1中断计数 55
3.13 TIMER0控制单只LED闪烁 58
3.14 TIMER0控制数码管动态管显示 62
3.15 TIMER0控制8×8LED点阵屏显示数字 65
3.16 TIMER0控制门铃声音输出 68
3.17 定时器控制交通指示灯 70
3.18 TIMER1控制音阶演奏 72
3.19 TIMER0、TIMER1及TIMER2实现外部信号计数与显示 75
3.20 TIMER0、TIMER1及INT0控制报警器与旋转灯 77
3.21 按键控制定时器选播多段音乐 79
3.22 键控看门狗 82
3.23 双机串口双向通信 84
3.24 PC与单片机双向通信 90
3.25 单片机内置EEPROM读/写测试 95
第4章 硬件应用 99
4.1 74HC138译码器与反向缓冲器控制数码管显示 100
4.2 串入并出芯片74HC595控制数码管显示四位数字 103
4.3 用74HC164驱动多只数码管显示 106
4.4 并串转换器74HC165应用 110
4.5 用74HC148扩展中断 112
4.6 串口发送数据到2片8×8点阵屏滚动显示 115
4.7 数码管BCD解码驱动器CD4511与DM7447应用 117
4.8 62256RAM扩展内存 119
4.9 用8255实现接口扩展 121
4.10 可编程接口芯片8155应用 124
4.11 串行共阴显示驱动器控制4+2+2集成式数码管显示 129
4.12 14段与16段数码管演示 133
4.13 16键解码芯片74C922应用 136
4.14 1602字符液晶工作于8位模式直接驱动显示 139
4.15 1602液晶显示DS1302实时时钟 148
4.16 1602液晶屏工作于8位模式由74LS373控制显示 153
4.17 1602液晶屏工作于4位模式实时显示当前时间 155
4.18 1602液晶屏显示DS12887实时时钟 159
4.19 时钟日历芯片PCF8583应用 167
4.20 2×20串行字符液晶屏显示 174
4.21 LGM12864液晶屏显示程序 177
4.22 TG126410液晶屏串行模式显示 184
4.23 Nokia7110液晶屏菜单控制程序 192
4.24 T6963C液晶屏图文演示 199
4.25 ADC0832 A/D转换与LCD显示 211
4.26 用DAC0832生成锯齿波 215
4.27 ADC0808 PWM实验 217
4.28 ADC0809 A/D转换与显示 220
4.29 用DAC0808实现数字调压 221
4.30 16位A/D转换芯片LTC1864应用 223
4.31 I2C接口存储器AT24C04读/写与显示 225
4.32 I2C存储器设计的中文硬件字库应用 233
4.33 I2C接口4通道A/D与单通道D/A转换器PCF8591应用 237
4.34 I2C接口DS1621温度传感器测试 241
4.35 用兼容I2C接口的MAX6953驱动4片5×7点阵显示器 246
4.36 用I2C接口控制MAX6955驱动16段数码管显示 250
4.37 I2C接口数字电位器AD5242应用 254
4.38 SPI接口存储器AT25F1024读/写与显示 257
4.39 SPI接口温度传感器TC72应用测试 264
4.40 温度传感器LM35全量程应用测试 268
4.41 SHT75温湿度传感器测试 272
4.42 直流电机正、反转及PWM调速控制 278
4.43 正反转可控的步进电机 281
4.44 ULN2803驱动点阵屏仿电梯数字滚动显示 284
4.45 液晶显示MPX4250压力值 286
4.46 12864LCD显示24C08保存的开机画面 289
4.47 用M145026与M145027设计的无线收发系统 293
4.48 DS18B20温度传感器测试 296
4.49 1-Wire式可寻址开关DS2405应用测试 303
4.50 MMC存储卡测试 307
第5章 综合设计 316
5.1 带日历时钟及温度显示的电子万年历 316
5.2 用8051+1601LCD设计的整型计算器 321
5.3 电子秤仿真设计 328
5.4 1602液晶屏显示仿手机键盘按键字符 332
5.5 用24C04与1602液晶屏设计的简易加密电子锁 336
5.6 1-Wire总线器件ROM搜索与多点温度监测 341
5.7 高仿真数码管电子钟设计 356
5.8 用DS1302与12864LCD设计的可调式中文电子日历 360
5.9 用T6963C液晶屏设计的指针式电子钟 366
5.10 T6963C液晶屏中文显示温度与时间 370
5.11 T6963C液晶屏曲线显示ADC0832两路A/D转换结果 372
5.12 温度控制直流电机转速 374
5.13 用74LS595与74LS154设计的16×16点阵屏 377
5.14 用8255与74LS154设计的16×16点阵屏 379
5.15 红外遥控收发仿真 381
5.16 GP2D12红外测距传感器应用 388
5.17 三端可调正稳压器LM317应用测试 395
5.18 数码管显示的K型热电偶温度计 399
5.19 交流电压检测与数字显示仿真 403
5.20 用MCP3421与RTD-PT100设计的铂电阻温度计 407
5.21 可接收串口信息的带中英文硬字库的80×16 LED点阵屏 414
5.22 模拟射击训练游戏 422
5.23 GPS仿真 427
5.24 温室监控系统仿真 431
5.25 基于Modbus总线的数据采集与开关控制系统设计仿真 437

建议你到脚本之家网站去搜索一下看看有没有这本书的电子档。

热点内容
安卓系统密码忘了怎么办 发布:2025-02-13 21:49:28 浏览:971
找回密码发送信息是什么意思 发布:2025-02-13 21:49:26 浏览:639
织梦通用源码 发布:2025-02-13 21:48:41 浏览:438
pid算法调速 发布:2025-02-13 21:20:31 浏览:686
脚本中new 发布:2025-02-13 21:00:11 浏览:741
什么配置的笔记本电脑能玩神武 发布:2025-02-13 20:54:40 浏览:179
挑选云服务器需要注意什么 发布:2025-02-13 20:53:31 浏览:98
加密滴胶卡 发布:2025-02-13 20:30:48 浏览:275
javalogin 发布:2025-02-13 20:25:48 浏览:427
智联招聘无法上传照片 发布:2025-02-13 20:16:03 浏览:529