大家好,这里是淇妙小屋,一个分享技术,分享生活的博主。后续会发布MySQL,Redis,并发,JVM,分布式等面试热点知识,以及Java学习路线,面试重点,职业规划,面经等相关博客 转载请标明出处!
我的掘金主页——https://juejin.cn/user/2766784438474925,欢迎大家关注
Lock接口定义了锁的API操作,用于实现java中锁机制
public interface Lock {
//如果锁可用,则获得锁后返回
//如果锁不可用,那么当前线程会阻塞,直到获取锁后才会返回
void lock();
//可中断的获取锁(获得锁的过程可中断)
//如果锁可用,则获得锁后返回
//如果锁不可用,那么线程会阻塞获取锁,阻塞获取锁的过程是可中断的,受到中断会抛出InterruptedException
void lockInterruptibly() throws InterruptedException;
//非阻塞的尝试获得锁
//如果锁可用,获得锁后,返回true
//如果锁不可用,返回false
boolean tryLock();
//尝试获取锁(获得锁的过程可中断)
//如果锁可用,获得锁后,返回true
//如果锁不可用,那么在指定时间内会不断的尝试获得锁
//如果成功获得锁——返回true
//如果被中断——抛出InterruptedException
//如果超时——返回false
boolean tryLock(long time, TimeUnit unit) throws InterruptedException;
//释放锁
void unlock();
//获取Condition对象,Condition对象与当前Lock对象绑定,当前线程只有获得了锁
//才能调用该Condition对象的await()方法,而调用后,当前线程将释放锁,进入Conditon对象的等待队列中WATING
//当其他线程调用Condition对象的signal(),才会唤醒Condition对象的等待队列中的WATING线程
Condition newCondition();
}
//Condition对象——1.相当于一个等待队列 2.必须与一个锁实例绑定 3.一个锁实例可以有多个Condition对象
//相当于monitor对象的WaitSet
//必须持有Condition对象绑定的锁,才可以调用其方法
public interface Condition {
//相当于Object.wait(),可中断
//持有锁的线程释放锁,进入等待队列中,线程状态更变为WATING,直到以下2种情况醒来
//1.有其他线程调用等待队列的signal()或signalAll()
//2.被其他线程中断
//醒来后的线程会从等待队列移动到锁实例的同步队列,状态由WAITING更改为BLOKING
void await() throws InterruptedException;
//同await(),但是不可中断
void awaitUninterruptibly();
//同 await(),但是多了一种唤醒情况——等待超时(单位纳秒)
long awaitNanos(long nanosTimeout) throws InterruptedException;
//同 await(),但是多了一种唤醒情况——等待超时
boolean await(long time, TimeUnit unit) throws InterruptedException;
//同 await(),但是多了一种唤醒情况——等待超时
boolean awaitUntil(Date deadline) throws InterruptedException;
//将等待队列中的首节点移动到锁实例的同步队列,然后通过LockSupport唤醒线程
void signal();
//将等待队列中的全部节点移动到锁实例的同步队列,然后通过LockSupport唤醒线程
void signalAll();
}
AbstractQueuedSynchronizer抽象队列同步器——用于构建锁或其他同步组件的基础框架
子类通过继承AQS并实现它的抽象方法来实现锁
AQS支持两种模式——独占模式,共享模式
AOS的核心字段——exclusiveOwnerThread
AQS最核心字段——state
Node的状态——waitStatus
AQS有5个方法供子类锁去实现
AQS独占模式下
同步队列中,只有当节点的前继节点是首节点,才能尝试取得锁,原因如下
过程基本与获取锁相同
区别在于
共享模式与独占模式的区别在于——同一时刻是否有多个线程可以同时获取到锁
可重入:任意线程获得锁后能够再次获取该锁而不会被锁阻塞
ReentrantLock实现了AQS的独占模式,是一个可重入锁,还分为 公平锁与 非公平锁
非公平锁的效率高于公平锁
非公平锁可能出现 线程饥饿问题——部分线程迟迟无法获得资源
ReentrantLock大多数方法的实现都是Sync及其子类来完成,ReentrantLock只是对外暴露了接口
FairSync和NonfairSync的 lock() 和 tryAcquire() 逻辑不同
上述2点保证了公平锁一定是——先对锁进行获取请求的线程一定先获得锁,而非公平锁不一定
公平锁释放锁与非公平锁释放锁采用同一个逻辑
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。