从源码的角度理解ReentrantLock的实现

package java.util.concurrent.locks;
import java.util.concurrent.TimeUnit;
import java.util.Collection;

/*
* 阅读本文前,最好先了解一下CAS和AQS,然后有疑问下方给我留言,大家一起学习
* 不要随便Copy别人的博客,这个习惯不好
* ReentrantLock中实现了两套锁机制
* 一个是NonfairSync(非公平锁),另一个是FairSync(公平锁)
* 公平与非公平不在于如何改变队列中排队线程的优先级,
* 而在于新的线程来了,是否可以发生抢占
* 非公平锁优先让加入线程抢占锁,抢占失败后交给AQS入队处理
* 而公平锁直接交给AQS处理
*/
public class ReentrantLock implements Lock, java.io.Serializable {
    private static final long serialVersionUID = 7373984872572414699L;

    
    // 锁的类型,公平锁和非公平锁都继承了这个抽象内部类
    private final Sync sync;

   
   // 抽象内部类继承了AQS,强烈建议子路老师的AQS视频(自己看很难学的明白)
   // 你会发现这个类中的nonfairTryAcquire是专为非公平锁设计的
   // 前面说过了,非公平多了一段抢占的逻辑代码,而不是直接交给AQS处理
    abstract static class Sync extends AbstractQueuedSynchronizer {
        private static final long serialVersionUID = -5179523762034025860L;

        // 加锁方法,子类需要实现这个方法
        abstract void lock();

        // 非公平的尝试获取锁,注意,进到这个代码块里的可不止一个线程
        final boolean nonfairTryAcquire(int acquires) {
            // 获取当前工作的线程
            final Thread current = Thread.currentThread();
            // 获取锁的状态 0表示没有线程获取锁,大于0表示锁已被占用
            // 为什么不直接说1而是说大于0呢,因为可重入锁允许持有锁的线程
            // 再次获取锁,所以可能 0 + 1 + 1 ..... 就是一个大于0的数了
            int c = getState();

            // 如果锁没有其它线程占用
            // 注意,由于是多线程,进入该代码块的线程不止一个
            // 由于指令重排,c的值还没有来得及被修改,
            // 就被好多线程进行比较,全部返回true
            if (c == 0) {
                // CAS的算法修改c的值(原子修改c的值)
                // 注意,进入该代码块的线程只有一个,就是修改c值成功的那个
                if (compareAndSetState(0, acquires)) {
                    // 把当前的线程持有者设置为current,也就是进入了该代码块的线程
                    setExclusiveOwnerThread(current);
                    // 成功返回
                    return true;
                }
            }

            // 跳到这里,说明上面的if不满足,也就是锁被占用了
            // 锁被占用了,要看看是哪个线程占用的锁,如果是正在工作的线程再一次
            // 获取锁,是允许它再一次获取锁的,这个就叫可重入,当然
            // 上了几次锁,解锁的时候就要解几次锁

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值