AQS如何实现ReentrantLock

1. AQS如何实现ReentrantLock的lock()和unlock()

一个AQS维护一个“同步队列”;

AQS实现了一个“锁状态”:private volatile int state;   

       采用CAS控制并发的“锁状态”修改,哪个线程设置1成功就获取了锁;否者就生成一个node加入AQS的“同步队列”中。然后就调用Unsafe.park()阻塞此线程。等待另一个线程unlock后,就被唤醒,然后将此node从AQS的“同步队列”中移除。然后执行业务代码。


       而unlock时就调用Unsafe.unpark唤醒“同步队列”中的等待时间最长的节点(公平锁为例)。

2. AQS如何实现ReentrantLock.newCondition()的await()和signal()

一个condition维护一个“等待队列”

condition await()方法,将当前线程添加进入一个condition维护的“等待队列”的队尾(node状态为CONDITION)。接着调用ReentrantLock.unlock相同流程释放锁;

然后调用native方法LockSupport.park();阻塞此线程。 等待condition signal()调用LockSupport.unpark()唤醒此线程;唤醒后此线程将调用与ReentrantLock.lock()类似流程获取锁,

获取到了之后就进入从await()返回执行后续流程。


condition signal()方法从wait队列中获取第一个node,将node状态修改为SIGNAL,并且将此node添加到Sync队列中。调用LockSupport.park();唤醒await()线程。

3. Unsafe理解:
Unsafe使用了linux系统的mutex(互斥量),condition(条件变量)来实现的。

4. Synchronize和AQS区别

4.1 Synchronize实现:

通过Synchronize包装代码块可以看出,其实现是基于字节码的Monitor来实现的。可见:Synchronize的monitor jvm实现就比较重了,是指定对象的加锁解锁;而且还有锁升级的过程(偏向锁,轻量级锁,重量级锁)。

Synchronize不支持加锁过程中响应线程中断。

4.2 AQS的实现:

底层是基于这个方法来实现锁:jdk.internal.misc.Unsafe#park

从AQS的源码实现可以看出,ReetrantLock只需要底层提供线程阻塞和线程唤醒的功能(Unsafe#park是入参只有线程的statis方法),unpark可以释放park,而且假如当前线程没有park,下次调用park也会自动释放,期间的是否获得锁就是通过java代码再次循环判断;

AQS还实现了丰富的锁功能,ReetrantLock,公平锁,非公平锁,信号量,门栓等功能。是通过jdk来实现的。

参考:

https://www.jianshu.com/p/7eccb3e6a88a

AbstractQueuedSynchronizer(AQS)超详细解析_枫_Maple的博客-CSDN博客

https://blog.csdn.net/m0_38057941/article/details/120105662

https://blog.csdn.net/qq_34069570/article/details/128120295
https://blog.csdn.net/themagickeyjianan/article/details/111267360

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值