ReentrantLock分为公平锁和非公平锁,底层如何实现?
不管哪种锁,他们的底层都会使用AQS来进行排队,它们的区别在于线程在使用Lock()方法时:
- 如果是公平锁,会先检查AQS队列是否存在线程排队,如果有线程排队,则当前线程也进行排队。
- 如果是非公平锁,则不会去检查是否有线程排队,而是直接竞争锁。
如果没竞争到锁,不管是公平锁还是非公平锁,都会进行排队,当锁释放时,都是唤醒排在最前面的线程,所以非公平锁只是体现在了线程加锁阶段,而没有体现在线程被唤醒阶段。
ReentrantLock是可重入锁,不管是公平锁还是非公平锁都是可重入的。(同一线程可重复添加同一把锁)
锁升级的过程:
1:偏向锁:在锁对象的对象头中记录一下当前获取到该锁的线程ID,该线程如果下次又来获取,该锁就可以直接获取到了,支持锁重入。
2:轻量级锁:由偏向锁升级而来,当一个线程获取到锁后,此时这种锁是偏向锁,此时如果有第二个线程来竞争锁,偏向锁会升级成轻量级锁,之所以叫轻量级锁,是为了和重量级锁区别开来,轻量级锁是通过自旋来实现的,并不会去阻塞进程。
3:如果自旋次数较多,则会升级成重量级锁。重量级锁会阻塞进程。
4:自旋锁:在线程获取锁的过程中,不回去阻塞进程,也就无所谓唤醒线程,阻塞和唤醒这俩步骤都是操作系统进行的,比较耗时间,自旋锁是线程通过CAS获取预期的一个标记,如果没有获取到,则继续进行循环,没有太大操作系统资源,比较轻量。