可重入原理
什么是可重入:当线程请求一个由其它线程持有的对象锁时,该线程会阻塞,而当线程请求由自己持有的对象锁时,如果该锁是重入锁,请求就会成功,否则阻塞。
重入锁实现可重入性原理或机制是:每一个锁关联一个线程持有者和计数器,当计数器为 0 时表示该锁没有被任何线程持有,那么任何线程都可能获得该锁而调用相应的方法;当某一线程请求成功后,JVM会记下锁的持有线程,并且将计数器置为 1;此时其它线程请求该锁,则必须等待;而该持有锁的线程如果再次请求这个锁,就可以再次拿到这个锁,同时计数器会递增;当线程退出同步代码块时,计数器会递减,如果计数器为 0,则释放该锁。具体源码如下
可打断原理
不可打断模式
在此模式下,即使它被打断,仍会驻留在 AQS 队列中,一直要等到获得锁后方能得知自己被打断了
可打断模式
可打断:本线程在等待获得锁的过程中,别的线程可以中止我的等待;
ReentrantLock不可打断模式:即使被打断,仅仅是打断标识设置为true,但是仍然线程会在AQS队列中,获得锁之后能够继续执行; ReentrantLock可打断模式:源码层面当unpark之后,直接进入异常,抛出,不会再进入死循环;
公平锁实现原理
线程在获取锁时以公平的形式进行,没有线程占用锁时可以直接获取锁成功,已经有线程占用锁或者已经有人在排队时将进入队列排队等待。公平锁不会出现饥饿效应,所有的线程都有可以获取到锁,但对CPU唤醒线程的开销较大,线程越多开销越大
非公平锁原理: 成员变量 sync = new NonfairSync(默认); 加锁时:compareAndSetState,尝试改变状态,成功就把Owner设置为当前线程,失败就再tryAcquire一次,还是失败,就创建一个节点对象,把线程加到等待队列(双向链表)里面去,park住当前线程; 释放锁:两种情况,一是唤醒的时候没有加锁的来竞争,唤醒head的后继结点,unpark它,然后把head节点链接到next等待的线程;二是有加锁的来竞争并且竞争成功,owner是别人,自己继续阻塞park;
条件变量实现原理
每个条件变量其实就对应着一个等待队列,其实现类是 ConditionObject
每一个条件变量Condition都对应一个ConditionObject,含有firstWaite和lastWaiter指针。await:把线程加入到ConditionObject的链表中去,释放掉该线程所有的锁,把自己park住,然后唤醒下一个节点; signal:必须要锁的持有者来调用该方法,把ConditionObject链表中的第一个线程转移到AQS的等待队列中;
await 流程
接下来进入 AQS 的 fullyRelease 流程,释放同步器上的锁
unpark AQS 队列中的下一个节点,竞争锁,假设没有其他竞争线程,那么 Thread-1 竞争成功
park 阻塞 Thread-0
signal 流程
假设 Thread-1 要来唤醒 Thread-0
进入 ConditionObject 的 doSignal 流程,取得等待队列中第一个 Node,即 Thread-0 所在 Node
执行 transferForSignal 流程,将该 Node 加入 AQS 队列尾部,将 Thread-0 的 waitStatus 改为 0,Thread-3 的waitStatus 改为 -1
Thread-1 释放锁,进入 unlock 流程,略
到此这篇条件变量是什么(条件变量原理)的文章就介绍到这了,更多相关内容请继续浏览下面的相关 推荐文章,希望大家都能在编程的领域有一番成就!版权声明:
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若内容造成侵权、违法违规、事实不符,请将相关资料发送至xkadmin@xkablog.com进行投诉反馈,一经查实,立即处理!
转载请注明出处,原文链接:https://www.xkablog.com/bcyy/47294.html