1.ReentrantLock 源码解析 | 京东云技术团队
2.基于GSM模块动态密码锁,随机锁源每次开锁的码随码锁时候GSM模块都会发一条6位随机数字码到手机短信的C语言编程,求大神
3.面试突击46:公平锁和非公平锁有什么区别?
ReentrantLock 源码解析 | 京东云技术团队
并发指同一时间内进行了多个线程。机密机并发问题是随机锁源多个线程对同一资源进行操作时产生的问题。通过加锁可以解决并发问题,码随码锁ReentrantLock 是机密机bi 源码 python锁的一种。
1 ReentrantLock
1.1 定义
ReentrantLock 是随机锁源 Lock 接口的实现类,可以手动的码随码锁对某一段进行加锁。ReentrantLock 可重入锁,机密机具有可重入性,随机锁源并且支持可中断锁。码随码锁其内部对锁的机密机控制有两种实现,一种为公平锁,随机锁源另一种为非公平锁.
1.2 实现原理
ReentrantLock 的码随码锁实现原理为 volatile+CAS。想要说明 volatile 和 CAS 首先要说明 JMM。机密机
1.2.1 JMM
JMM (java 内存模型 Java Memory Model 简称 JMM) 本身是一个抽象的概念,并不在内存中真实存在的,它描述的是一组规范或者规则,通过这组规范定义了程序中各个变量的访问方式.
由于 JMM 运行的程序的实体是线程。而每个线程创建时 JMM 都会为其创建一个自己的工作内存 (栈空间), 工作内存是每个线程的私有数据区域。而 java 内存模型中规定所有的变量都存储在主内存中,主内存是共享内存区域,所有线程都可以访问,但线程的变量的操作 (读取赋值等) 必须在自己的工作内存中去进行,首先要将变量从主存拷贝到自己的工作内存中,然后对变量进行操作,分身app源码操作完成后再将变量操作完后的新值写回主内存,不能直接操作主内存的变量,各个线程的工作内存中存储着主内存的变量拷贝的副本,因不同的线程间无法访问对方的工作内存,线程间的通信必须在主内存来完成。
如图所示:线程 A 对变量 A 的操作,只能是从主内存中拷贝到线程中,再写回到主内存中。
1.2.2 volatile
volatile 是 JAVA 的关键字用于修饰变量,是 java 虚拟机的轻量同步机制,volatile 不能保证原子性。 作用:
作用:CAS 会使用现代处理器上提供的高效机器级别原子指令,这些原子指令以原子方式对内存执行读 - 改 - 写操作。
1.2.4 AQSAQS 的全称是 AbstractQueuedSynchronizer(抽象的队列式的同步器),AQS 定义了一套多线程访问共享资源的同步器框架。
AQS 主要包含两部分内容:共享资源和等待队列。AQS 底层已经对这两部分内容提供了很多方法。
2 源码解析
ReentrantLock 在包 java.util.concurrent.locks 下,实现 Lock 接口。
2.1 lock 方法
lock 分为公平锁和非公平锁。
公平锁:
非公平锁:上来先尝试将 state 从 0 修改为 1,如果成功,代表获取锁资源。如果没有成功,调用 acquire。健身会所源码state 是 AQS 中的一个由 volatile 修饰的 int 类型变量,多个线程会通过 CAS 的方式修改 state,在并发情况下,只会有一个线程成功的修改 state。
2.2 acquire 方法
acquire 是一个业务方法,里面并没有实际的业务处理,都是在调用其他方法。
2.3 tryAcquire 方法
tryAcquire 分为公平和非公平两种。
公平:
非公平:
2.4 addWaiter 方法
在获取锁资源失败后,需要将当前线程封装为 Node 对象,并且插入到 AQS 队列的末尾。
2.5 acquireQueued 方法
2.6 unlock 方法
释放锁资源,将 state 减 1, 如果 state 减为 0 了,唤醒在队列中排队的 Node。
3 使用实例
3.1 公平锁
1. 代码:
2. 执行结果:
3. 小结:
公平锁可以保证每个线程获取锁的机会是相等的。
3.2 非公平锁
1. 代码:
2. 执行结果:
3. 小结:
非公平锁每个线程获取锁的机会是随机的。
3.3 忽略重复操作
1. 代码:
2. 执行结果:
3. 小结:
当线程持有锁时,不会重复执行,可以用来防止定时任务重复执行或者页面事件多次触发时不会重复触发。
3.4 超时不执行
1. 代码:
2. 执行结果:
3. 小结:
超时不执行可以防止由于资源处理不当长时间占用资源产生的死锁问题。
4 总结
并发是现在软件系统不可避免的问题,ReentrantLock 是可重入的独占锁,比起 synchronized 功能更加丰富,支持公平锁实现,支持中断响应以及限时等待等,内核源码包是处理并发问题很好的解决方案。
基于GSM模块动态密码锁,每次开锁的时候GSM模块都会发一条6位随机数字码到手机短信的C语言编程,求大神
近年来,随着生活水平的不断改善,个人财富日益增长,人们对安全防盗的要求也逐渐提高。安全可靠、使用方便的电子密码锁成了人们防盗的首选。以Max PlusⅡ(Multiple Array Matrix and ProgrammingLogic User SystemⅡ,多阵列矩阵及可编程逻辑用户系统Ⅱ)为工作平台,使用PLD可编程器件和VHDL语言设计的带音乐的电子密码锁具有密码预置,误码锁死及开锁音乐提示等功能。这种设计不仅简化了系统结构,降低了成本,更提高了系统的可靠和保密性。采用PLD可编程逻辑器件开发的数字系统,可以方便地升级和改进。
1 设计思路
密码锁电路由键盘控制、密码设置和音乐演奏三大功能模块组成,原理如图1所示。Count,Keyvalue,Contrl,Smdisplay构成键盘控制模块,iview admin源码Songer是音乐演奏模块,Set是密码设置模块。
1.1 键盘控制
键盘主要完成向系统输入数据,传送命令等功能。它是一个机械弹性按键开关的集合,利用机械触点的合、断作用产生高、低电平。通过对电平高低状态的检测,以确认按键按下与否。一个电压信号通过机械触点的断开、闭合过程的波形如图2所示。
在该键盘电路中,Count模块提供键盘的行扫描信号Q[3..0]。在没有按键按下时,信号EN为高电平,行扫描输出信号Q[3..0]的循环变化顺序为 OO (依次扫描4行按键);当有按键按下时,信号EN为低电平,行扫描输出信号Q[3..0]停止扫描,并锁存当前的行扫描值。例如按下第一行的按键,那么Q[3..O]=。
Keyvalue模块的主要功能是对输入按键的行信号Q[3..0]和列信号[3..0]的当前组合值进行判断来确定输入按键的键值。
Contrl模块的主要功能是实现按键的消抖,判断是否有按键按下。确保对按键的提取处于图2所示的闭合稳定时间范围内,这就对本模块的输入时钟信号有一定的要求,在本设计中该模块输入的时钟信号频率为 Hz。Smdisplay模块主要是完成数码管动态扫描和七段译码显示的功能。
1.2 音乐演奏电路Songer
根据声乐学知识,组成乐曲的每个音符的发音频率值及其持续的时间是乐曲能连续演奏所需的两个基本要素。获得这两个要素所对应的数值以及通过纯硬件的手段来利用这些数值实现所希望乐曲的演奏效果是关键。如图3所示,该电路需要由NOTETABS(音调发生器)、TONETABA、SPEAKER(数控分频器)三个模块组成,分别实现了声音产生、节拍控制、音调控制的功能。
1.3 密码设置
Set模块是实现密码锁功能的核心模块。其主要作用是设置密码,Set为设置密码的有效信号,可以实现修改密码的功能。En为输入密码确认信号,当输入完六位密码后确认输入,一旦输入的密码跟所设置的密码一致时,则输出信号OP有效(高电平);OP控制演奏音乐,此时音乐响起。若密码不正确,则指示输入错误及输入次数,输完三次无效后密码锁锁死,必须由RESET信号(启动信号,给一个低电平)重新打开密码锁功能。
2 电路的VHDL描述
键盘控制电路,音乐演奏电路以及密码设置模块均使用硬件描述语言VHSIC Hardware Description Lan-guage(VHDL)设计而成。例如:TONETABA的VHDL模型如下:
VHDL语言具有很强的电路描述和建模能力,能从多个层次对数字系统进行建模和描述,支持各种模式的设计方法:自顶向下与自底向上或混合方法
面试突击:公平锁和非公平锁有什么区别?
从公平的角度来说,Java 中的锁总共可分为两类:公平锁和非公平锁。但公平锁和非公平锁有哪些区别?孰优孰劣呢?在 Java 中的应用场景又有哪些呢?接下来我们一起来看。正文公平锁:每个线程获取锁的顺序是按照线程访问锁的先后顺序获取的,最前面的线程总是最先获取到锁。 非公平锁:每个线程获取锁的顺序是随机的,并不会遵循先来先得的规则,所有线程会竞争获取锁。 举个例子,公平锁就像开车经过收费站一样,所有的车都会排队等待通过,先来的车先通过,如下图所示:
通过收费站的顺序也是先来先到,分别是张三、李四、王五,这种情况就是公平锁。 而非公平锁相当于,来了一个强行加塞的老司机,它不会准守排队规则,来了之后就会试图强行加塞,如果加塞成功就顺利通过,当然也有可能加塞失败,如果失败就乖乖去后面排队,这种情况就是非公平锁。
应用场景在 Java 语言中,锁 synchronized 和 ReentrantLock 默认都是非公平锁,当然我们在创建 ReentrantLock 时,可以手动指定其为公平锁,但 synchronized 只能为非公平锁。 ReentrantLock 默认为非公平锁可以在它的源码实现中得到验证,如下源码所示:当使用 new ReentrantLock(true) 时,可以创建公平锁,如下源码所示:
公平和非公平锁代码演示接下来我们使用 ReentrantLock 来演示一下公平锁和非公平锁的执行差异,首先定义一个公平锁,开启 3 个线程,每个线程执行两次加锁和释放锁并打印线程名的操作,如下代码所示:
import?java.util.concurrent.locks.Lock;import?java.util.concurrent.locks.ReentrantLock;public?class?ReentrantLockFairTest?{ static?Lock?lock?=?new?ReentrantLock(true);public?static?void?main(String[]?args)?throws?InterruptedException?{ for?(int?i?=?0;?i?<?3;?i++)?{ new?Thread(()?->?{ for?(int?j?=?0;?j?<?2;?j++)?{ lock.lock();System.out.println("当前线程:"?+?Thread.currentThread().getName());lock.unlock();}}).start();}}}以上程序的执行结果如下图所示:接下来我们使用非公平锁来执行上面的代码,具体实现如下:
import?java.util.concurrent.locks.Lock;import?java.util.concurrent.locks.ReentrantLock;public?class?ReentrantLockFairTest?{ static?Lock?lock?=?new?ReentrantLock();public?static?void?main(String[]?args)?throws?InterruptedException?{ for?(int?i?=?0;?i?<?3;?i++)?{ new?Thread(()?->?{ for?(int?j?=?0;?j?<?2;?j++)?{ lock.lock();System.out.println("当前线程:"?+?Thread.currentThread().getName());lock.unlock();}}).start();}}}以上程序的执行结果如下图所示:从上述结果可以看出,使用公平锁线程获取锁的顺序是:A -> B -> C -> A -> B -> C,也就是按顺序获取锁。而非公平锁,获取锁的顺序是 A -> A -> B -> B -> C -> C,原因是所有线程都争抢锁时,因为当前执行线程处于活跃状态,其他线程属于等待状态(还需要被唤醒),所以当前线程总是会先获取到锁,所以最终获取锁的顺序是:A -> A -> B -> B -> C -> C。
执行流程分析公平锁执行流程获取锁时,先将线程自己添加到等待队列的队尾并休眠,当某线程用完锁之后,会去唤醒等待队列中队首的线程尝试去获取锁,锁的使用顺序也就是队列中的先后顺序,在整个过程中,线程会从运行状态切换到休眠状态,再从休眠状态恢复成运行状态,但线程每次休眠和恢复都需要从用户态转换成内核态,而这个状态的转换是比较慢的,所以公平锁的执行速度会比较慢。
非公平锁执行流程当线程获取锁时,会先通过 CAS 尝试获取锁,如果获取成功就直接拥有锁,如果获取锁失败才会进入等待队列,等待下次尝试获取锁。这样做的好处是,获取锁不用遵循先到先得的规则,从而避免了线程休眠和恢复的操作,这样就加速了程序的执行效率。 公平锁和非公平锁的性能测试结果如下,以下测试数据来自于《Java并发编程实战》:
从上述结果可以看出,使用非公平锁的吞吐率(单位时间内成功获取锁的平均速率)要比公平锁高很多。
优缺点分析公平锁的优点是按序平均分配锁资源,不会出现线程饿死的情况,它的缺点是按序唤醒线程的开销大,执行性能不高。 非公平锁的优点是执行效率高,谁先获取到锁,锁就属于谁,不会“按资排辈”以及顺序唤醒,但缺点是资源分配随机性强,可能会出现线程饿死的情况。
总结在 Java 语言中,锁的默认实现都是非公平锁,原因是非公平锁的效率更高,使用 ReentrantLock 可以手动指定其为公平锁。非公平锁注重的是性能,而公平锁注重的是锁资源的平均分配,所以我们要选择合适的场景来应用二者。
是非审之于己,毁誉听之于人,得失安之于数。
公众号:Java面试真题解析
面试合集:/post/