怎么深入理解ReentrantLock原理


这期内容当中小编将会给大家带来有关怎么深入理解ReentrantLock原理,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。ReentrantLock是个典型的独占模式AQS,同步状态为0时表示空闲。当有线程获取到空闲的同步状态时,它会将同步状态加1,将同步状态改为非空闲,于是其他线程挂起等待。在修改同步状态的同时,并记录下自己的线程,作为后续重入的依据,即一个线程持有某个对象的锁时,再次去获取这个对象的锁是可以成功的。如果是不可重入的锁的话,就会造成死锁。ReentrantLock会涉及到公平锁和非公平锁,实现关键在于成员变量sync的实现不同,这是锁实现互斥同步的核心。那公平锁和非公平锁是什么?有什么区别?公平锁是指当锁可用时,在锁上等待时间最长的线程将获得锁的使用权,即先进先出。而非公平锁则随机分配这种使用权,是一种抢占机制,是随机获得锁,并不是先来的一定能先得到锁。ReentrantLock提供了一个构造方法,可以实现公平锁或非公平锁:虽然公平锁在公平性得以保障,但因为公平的获取锁没有考虑到操作系统对线程的调度因素以及其他因素,会影响性能。虽然非公平模式效率比较高,但是非公平模式在申请获取锁的线程足够多,那么可能会造成某些线程长时间得不到锁,这就是非公平锁的“饥饿”问题。但大部分情况下我们使用非公平锁,因为其性能比公平锁好很多。但是公平锁能够避免线程饥饿,某些情况下也很有用。接下来看看ReentrantLock公平锁的实现:首先需要在构建函数中传入true创建好公平锁调用lock()进行上锁,直接acquire(1)上锁直接尝试获取锁,具体获取锁流程getState()获取同步状态state值,进行判断是否为0如果状态变量的值为0,说明暂时还没有人占有锁, 使用hasQueuedPredecessors()保证了不论是新的线程还是已经排队的线程都顺序使用锁,如果没有其它线程在排队,那么当前线程尝试更新state的值为1,并自己设置到exclusiveOwnerThread变量中,供后续自己可重入获取锁作准备如果exclusiveOwnerThread中为当前线程说明本身就占有着锁,现在又尝试获取锁,需要将状态变量的值state+1如果获取失败加入队列里,那具体怎么处理呢?通过自旋的方式,队列中线程不断进行尝试获取锁操作,中间是可以通过中断的方式打断,如果当前节点的前一个节点为head节点,则说明轮到自己获取锁了,调用tryAcquire()方法再次尝试获取锁
当前的Node的上一个节点不是Head,是需要判断是否需要阻塞,以及寻找安全点挂起。
在看完获取锁的流程,那么你知道ReentrantLock如何实现公平锁了吗?其实就是在tryAcquire()的实现中。在tryAcquire()的实现中使用了hasQueuedPredecessors()保证了线程先进先出FIFO的使用锁,不会产生”饥饿”问题,tryAcquire都会检查CLH队列中是否仍有前驱的元素,如果仍然有那么继续等待,通过这种方式来保证先来先服务的原则。那这样ReentrantLock如何实现可重入?是怎么重入的?其实也很简单,在获取锁后,设置一个标识变量为当前线程exclusiveOwnerThread,当线程再次进入判断exclusiveOwnerThread变量是否等于本线程来判断.当看完公平锁获取锁的流程,那其实我们也了解非公平锁获取锁,那我们来看看。其实非公平锁获取锁获取区别主要在于:构建函数中传入false或者为null,为创建非公平锁NonfairSync,true创建公平锁,非公平锁在获 香港云主机取锁的时候,先去检查state状态,再直接执行aqcuire(1),这样可以提高效率,
tryAcquire()中没有hasQueuedPredecessors()保证了不论是新的线程还是已经排队的线程都顺序使用锁。其他功能都类似。在理解了获取锁下,我们更好理解ReentrantLock::unlock()锁的释放,也比较简单。释放当前线程占用的锁
若释放成功,就需要唤醒等待队列中的线程,先查看头结点的状态是否为SIGNAL,如果是则唤醒头结点的下个节点关联的线程,如果释放失败那么返回false表示解锁失败。设置waitStatus为0,当头结点下一个节点不为空的时候,会直接唤醒该节点,如果该节点为空,则会队尾开始向前遍历,找到最后一个不为空的节点,然后唤醒。综合上面的ReentrantLock的可重入,可实现公平非公平锁的特性外,还具有哪些特性?支持线程中断,只是在线程上增加一个中断标志interrupted,并不会对运行中的线程有什么影响,具体需要根据这个中断标志干些什么,用户自己去决定。比如,实现了等待锁的时候,5秒没有获取到锁,中断等待,线程继续做其它事情。超时机制,在ReetrantLock::tryLock(long timeout, TimeUnit unit) 提供了超时获取锁的功能。它的语义是在指定的时间内如果获取到锁就返回true,获取不到则返回false。这种机制避免了线程无限期的等待锁释放。ReentrantLock支持等待可中断,可以中断等待中的线程ReentrantLock可实现公平锁ReentrantLock可实现选择性通知,即可以有多个Condition队列场景1:如果已加锁,则不再重复加锁,多用于进行非重要任务防止重复执行,如,清除无用临时文件,检查某些资源的可用性,数据备份操作等场景2:如果发现该操作已经在执行,则尝试等待一段时间,等待超时则不执行,防止由于资源处理不当长时间占用导致死锁情况场景3:如果发现该操作已经加锁,则等待一个一个加锁,主要用于对资源的争抢(如:文件操作,同步消息发送,有状态的操作等)场景4:可中断锁,取消正在同步运行的操作,来防止不正常操作长时间占用造成的阻塞上述就是小编为大家分享的怎么深入理解ReentrantLock原理了,如果刚好有类似的疑惑,不妨参照上述分析进行理解。如果想知道更多相关知识,欢迎关注开发云行业资讯频道。

相关推荐: 笔记本电脑SSD固态硬盘如何分区

这篇文章将为大家详细讲解有关笔记本电脑SSD固态硬盘如何分区,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。分区对固态硬盘的寿命没有任何影响,硬盘分区其实是一种格式化,高级的硬盘格式化,在创建硬盘分区的时候,会自动设置好各种参…

免责声明:本站发布的图片视频文字,以转载和分享为主,文章观点不代表本站立场,本站不承担相关法律责任;如果涉及侵权请联系邮箱:360163164@qq.com举报,并提供相关证据,经查实将立刻删除涉嫌侵权内容。

Like (0)
Donate 微信扫一扫 微信扫一扫
Previous 09/02 18:26
Next 09/02 18:27

相关推荐