显示锁-ReentrantLock

发布时间:2024年01月09日

1、概念:ReentrantLock实现了Lock接口,并且提供了和Synchronized相同的互斥性和内存可见性。另外,ReentrantLock并不是用来代替Synchronized的,而是当Synchronized的加锁机制不合适时,作为一种可选择的高级功能。

2、对比Synchronized

  • 皆可重入:两者都提供了可重入的语义。
  • ReentrantLock更加灵活:
    (1)ReentrantLock可以终止一个正在等待锁的线程。
    (2)设置轮询锁,尝试获取锁,设置一定次数,轮询该次数后依然没有获取到锁,则放弃获取。
    (3)设置定时锁,在规定时间内去获取锁,超过这个时间,则放弃获取。
  • ReentrantLock必须显示的加锁和释放锁,如果忘记在finally中忘记释放锁,那么就相当于埋下了一颗定时炸弹,因此具有一定的“危险性”;Synchronized在发生异常时会自动释放锁,避免了异常时的死锁。
  • 吞吐量:Java5.0时,ReentrantLock性能会好很多;到了Java6.0,两者的效果差不多。

3、公平锁和非公平锁

? ? ? ? 公平锁确保被阻塞的线程都能够获取到锁,避免了线程获取锁的饥饿现象;但是在激烈竞争的情况下,线程从内核态转变为用户态存在着严重的延迟,此时会带来性能的影响。

? ? ? ? 非公平锁则是让线程可以”插队“,在非公平锁的情况下,新来的线程只有在锁被别的线程持有时,才会进入队列,不然不会进入队列,而是立即参与竞争,如果竞争成功,则省去了线程状态切换的开销,这说明了某些情况下,非公平锁比公平锁性能要好。但是,非公平锁会出现饥饿现象。

? ? ? ? Synchronized是非公平锁。

????????ReentrantLock可以自主选择,默认是非公平锁;如果创建时传入true,则是公平锁。

    public ReentrantLock() {
        sync = new NonfairSync();
    }
 
    public ReentrantLock(boolean fair) {
        sync = fair ? new FairSync() : new NonfairSync();
    }

4、抉择

? ? ? ? 只有在内置锁无法满足要求的情况下,才应该去考虑ReentrantLock,ReentrantLock作为一种高级的备选方案,选择它的原因是因为它的高级功能。如若不然,有限考虑Synchronized。

5、原理

  1. 锁的竞争,通过互斥变量,使用CAS机制实现;没有竞争到锁的线程使用AbstractQueuedSynchronizer线程同步器来存储,同步器底层通过双向链表实现,当锁被释放之后,会从AQS队列头部唤醒一个线程。
  2. 锁重入原理:AQS里面有一个成员变量来保存当前获取到锁的的线程,如果该线程再次获取锁,那么就可以直接增加锁的重入次数,不会走竞争逻辑。
文章来源:https://blog.csdn.net/qq_42251944/article/details/135470674
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。