【公平锁与非公平锁】

ReentrantLock是 Java 中一个可重入的互斥锁,它既可以实现公平锁也可以实现非公平锁。以下是它们的实现原理:

一、非公平锁的实现原理

  1. 锁的获取:

    • 当一个线程调用ReentrantLocklock()方法尝试获取锁时,它会首先通过一个 CAS(Compare and Swap)操作尝试将锁的状态从“未锁定”变为“已锁定”,如果成功,则该线程直接获取到锁。
    • 如果 CAS 操作失败,说明锁已经被其他线程持有,当前线程会被加入到等待队列中。
  2. 线程等待与唤醒:

    • 等待的线程会被封装成一个Node对象,加入到同步队列(一个双向链表)中。每个Node对象都有一个前驱节点和一个后继节点,用于在队列中进行排序和等待唤醒。
    • 当持有锁的线程释放锁时,会通过唤醒同步队列中的第一个等待线程来实现锁的传递。被唤醒的线程会再次尝试获取锁,如果成功,则继续执行;如果失败,则继续在队列中等待。
  3. 非公平性体现:

    • 非公平锁的“非公平”体现在新的线程在尝试获取锁时,不管同步队列中是否有等待的线程,它都会直接进行 CAS 操作尝试获取锁。这就可能导致已经在等待队列中的线程长时间等待,而新的线程却能够直接获取到锁。

二、公平锁的实现原理

  1. 锁的获取:

    • 与非公平锁类似,线程调用lock()方法尝试获取锁时,也会首先尝试通过 CAS 操作获取锁。但是,在公平锁的情况下,如果同步队列中有等待的线程,新的线程不会直接进行 CAS 操作,而是会先加入到同步队列的末尾,然后等待被唤醒。
    • 这样就保证了线程获取锁的顺序是按照它们请求锁的时间顺序来的,先请求的线程先获取锁。
  2. 线程等待与唤醒:

    • 公平锁的等待和唤醒机制与非公平锁基本相同,都是将等待的线程封装成Node对象加入到同步队列中,当持有锁的线程释放锁时,唤醒同步队列中的第一个等待线程。
  3. 公平性体现:

    • 公平锁的“公平”体现在新的线程在尝试获取锁时,如果同步队列中有等待的线程,它会先加入到队列末尾,等待被唤醒。这样就确保了每个线程都有公平的机会获取锁,不会出现某个线程一直被忽略而其他线程不断获取锁的情况。

总的来说,ReentrantLock的公平锁和非公平锁的主要区别在于新线程获取锁的方式。非公平锁允许新线程在任何时候尝试获取锁,而公平锁要求新线程在同步队列中有等待线程时先加入到队列末尾等待被唤醒。公平锁在保证线程公平性的同时,可能会导致性能下降,因为它需要更多的线程上下文切换和队列操作。非公平锁在性能上可能更好,但可能会导致某些线程长时间等待。在实际应用中,可以根据具体的需求选择使用公平锁还是非公平锁。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

越来越亮

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值