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