JUC源码简析 ReentrantLock

相关阅读

简介

支持重进入的独占锁,使用内部持有的Sync类型的实例实现了Lock接口。
内部类Sync继承自AbstractQueuedSynchronizer,重写了父类的tryReleaseisHeldExclusively方法;定义抽象方法lock(),由子类实现;
内部类FairSync继承自Sync,以公平(先到先得)竞争锁的方式实现了lock()算法字节;
内部类NonfairSync继承自Sync,以非公平(不保证先到先得)竞争锁的方式实现了lock()算法细节;

源码简析

内部类——Sync

简介

重写了父类的tryReleaseisHeldExclusively方法;
定义抽象方法lock(),由子类实现;

abstract void lock();

tryRelease

protected final boolean tryRelease(int releases) {
    int c = getState() - releases;
    // 校验释放锁的线程是否时持有锁的线程
    if (Thread.currentThread() != getExclusiveOwnerThread())
        // 当前线程不是持有独占锁的线程,那么就是非法操作,需要抛出IllegalMonitorStateException
        throw new IllegalMonitorStateException();
    // 释放锁标识,默认未释放
    boolean free = false;
    if (c == 0) {
        // 资源为0,则表示本线程已释放锁
        free = true;
        // 清空持有锁线程信息
        setExclusiveOwnerThread(null);
    }
    // 更新锁资源
    setState(c);
    return free;
}

本方法只支持被持有独占锁的线程调用,所以不存在线程竞争,其它线程调用则会抛出异常IllegalMonitorStateException

isHeldExclusively

protected final boolean isHeldExclusively() {
    // 持有锁的线程是否是本线程
    return getExclusiveOwnerThread() == Thread.currentThread();
}

nonfairTryAcquire

final boolean nonfairTryAcquire(int acquires) {
    final Thread current = Thread.currentThread();
    int c = getState();
    // 如果当前锁资源还未被占用
    if (c == 0) {
        // CAS尝试获取锁资源,存在多线程竞争
        if (compareAndSetState(0, acquires)) {
            // 获取成功,设置本线程为持有锁线程
            setExclusiveOwnerThread(current);
            // true表示获取锁成功
            return true;
        }
    }
    // 锁资源已经被占用,则考虑是不是被自身占有的
    else if (current == getExclusiveOwnerThread()) {
        // 可重入的体现

        // 累加锁资源计数
        int nextc = c + acquires;
        if (nextc < 0)
            // 资源计数发生反转,需要抛出错误
            throw new Error("Maximum lock count exceeded");
        // 更新锁资源
        setState(nextc);
        // true表示获取锁成功
        return true;
    }
    // false表示获取锁成功
    return false;
}

本方式是以不公平竞争锁的方式实现的,不公平的体现为:新线程没有考虑当前是否已存在其它线程在等待获取锁,而是直接尝试获取锁;如果此时持有锁的线程恰好释放锁,那么新线程就可能获取锁成功,被释放锁线程唤醒的后继节点线程会因获取锁失败,再次设置头节点(头节点没有变化)的等待状态为SIGNAL,然后挂起,等待新线程释放锁时唤醒自身;

内部类——NonFairSync

简介

继承自Sync,实现非公平锁相关操作;
需要实现的方法为:

  1. 父类Sync的抽象方法lock
  2. 来自父类Sync继承的AbstractQueuedSynchronizer的抽象方法tryAcquire

lock

final void lock() {
    // CAS尝试获取独占锁,即假设锁资源还未被获取,然后占取锁资源
    if (compareAndSetState(0, 1))
        // 获取成功,设置本线程为持有锁线程
        setExclusiveOwnerThread(Thread.currentThread());
    else
        // 老老实实地获取锁
        acquire(1);
}

tryAcquire

protected final boolean tryAcquire(int acquires) {
    // 调用父类Sync的nonfaireTryAcquire实现
    return nonfairTryAcquire(acquires);
}

本方式是以不公平竞争锁的方式实现的,不公平的体现为:新线程没有考虑当前是否已存在其它线程在等待获取锁,而是直接尝试快速获取锁;如果此时持有锁的线程恰好释放锁,那么新线程就可能获取锁成功,被释放锁线程唤醒的后继节点线程会因获取锁失败,再次设置头节点(头节点没有变化)的等待状态为SIGNAL,然后挂起,等待新线程释放锁时唤醒自身;新线程尝试快速获取锁失败后,才老实地按照正常方式去获取锁;

内部类——FairSync

简介

继承自Sync,实现公平锁相关操作;
需要实现的方法为:

  1. 父类Sync的抽象方法lock
  2. 来自父类Sync继承的AbstractQueuedSynchronizer的抽象方法tryAcquire

lock

final void lock() {
    // 老老实实地获取锁,没有尝试快速获取锁
    acquire(1);
}

tryAcquire

protected final boolean tryAcquire(int acquires) {
    final Thread current = Thread.currentThread();
    int c = getState();
    // 如果当前锁资源还未被占用
    if (c == 0) {
        // 不存在等待获取锁的线程,才CAS尝试获取锁资源,存在多线程竞争
        if (!hasQueuedPredecessors() &&
            compareAndSetState(0, acquires)) {
            // 获取成功,设置本线程为持有锁线程
            setExclusiveOwnerThread(current);
            // true表示获取锁成功
            return true;
        }
    }
    // 锁资源已经被占用,则考虑是不是被自身占有的
    else if (current == getExclusiveOwnerThread()) {
        // 可重入的体现

        // 累加锁资源计数
        int nextc = c + acquires;
        if (nextc < 0)
            // 资源计数发生反转,需要抛出错误
            throw new Error("Maximum lock count exceeded");
        // 更新锁资源
        setState(nextc);
        // true表示获取锁成功
        return true;
    }
    // false表示获取锁成功
    return false;
}

// AbstractQueuedSynchronizer
public final boolean hasQueuedPredecessors() {
    // The correctness of this depends on head being initialized
    // before tail and on head.next being accurate if the current
    // thread is first in queue.
    Node t = tail; // Read fields in reverse initialization order
    Node h = head;
    Node s;
    // 头节点就是尾节点,则队列没有其它等待节点
    // 队列存在节点,且
    //     头节点的next不存在,即此时有新节点插入队列,刚更新尾节点,还未来得及更新旧尾节点的next,那么队列中存在其它等待节点(新节点)
    //     或者存在但不是本线程,那么队列中有其它等待节点
    // 否则,不存在其它等待节点,因为头节点的next就是本线程节点,这是等待队列中的节点线程尝试获取锁的情况
    return h != t &&
        ((s = h.next) == null || s.thread != Thread.currentThread());
}

本方式是以公平竞争锁的方式实现的,公平的体现为:新线程在尝试获取锁之前,会先考虑当前是否已存在其它线程在等待获取锁,如果存在则直接放弃获取锁;如果不存在,才尝试获取锁;

ReentrantLock

简介

实现了Lock接口,Lock接口的相关方法都是通过内部类Sync的实例实现;

构造方法

public ReentrantLock() {
    // 默认是非公平锁,使用场景更多
    sync = new NonfairSync();
}

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

Lock接口

public void lock() {
    sync.lock();
}

public void unlock() {
    sync.release(1);
}

public Condition newCondition() {
    return sync.newCondition();
}

测试

Demo

public class Demo {
    private int parties = 5;
    private ReentrantLock reentrantLock = new ReentrantLock();


    public static void main(String[] args) throws InterruptedException {
        Demo demo = new Demo();
        ExecutorService es = Executors.newFixedThreadPool(demo.parties);

        for (int i = 0; i < demo.parties; i++) {
            es.execute(new ReentrantLockTask(i, demo.reentrantLock));
        }
        es.shutdown();
    }


    private static class ReentrantLockTask implements Runnable {

        private ReentrantLock reentrantLock;
        private int index;


        ReentrantLockTask(int index, ReentrantLock reentrantLock) {
            this.reentrantLock = reentrantLock;
            this.index = index;
        }

        @Override
        public void run() {
            try {
                TimeUnit.SECONDS.sleep(5);
                System.out.println("Thread:" + index + " waits to get lock");
                reentrantLock.lock();
                System.out.println("Thread:" + index + " has get lock");

                TimeUnit.SECONDS.sleep(5);
                reentrantLock.unlock();
                System.out.println("Thread:" + index + " has released lock");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

测试结果

Thread:0 waits to get lock
Thread:3 waits to get lock
Thread:2 waits to get lock
Thread:4 waits to get lock
Thread:1 waits to get lock
Thread:0 has get lock
Thread:0 has released lock
Thread:2 has get lock
Thread:2 has released lock
Thread:3 has get lock
Thread:3 has released lock
Thread:1 has get lock
Thread:1 has released lock
Thread:4 has get lock
Thread:4 has released lock
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
对于计算机专业的学生而言,参加各类比赛能够带来多方面的益处,具体包括但不限于以下几点: 技能提升: 参与比赛促使学生深入学习和掌握计算机领域的专业知识与技能,如编程语言、算法设计、软件工程、网络安全等。 比赛通常涉及实际问题的解决,有助于将理论知识应用于实践中,增强问题解决能力。 实践经验: 大多数比赛都要求参赛者设计并实现解决方案,这提供了宝贵的动手操作机会,有助于积累项目经验。 实践经验对于计算机专业的学生尤为重要,因为雇主往往更青睐有实际项目背景的候选人。 团队合作: 许多比赛鼓励团队协作,这有助于培养学生的团队精神、沟通技巧和领导能力。 团队合作还能促进学生之间的知识共享和思维碰撞,有助于形成更全面的解决方案。 职业发展: 获奖经历可以显著增强简历的吸引力,为求职或继续深造提供有力支持。 某些比赛可能直接与企业合作,提供实习、工作机会或奖学金,为学生的职业生涯打开更多门路。 网络拓展: 比赛是结识同行业人才的好机会,可以帮助学生建立行业联系,这对于未来的职业发展非常重要。 奖金与荣誉: 许多比赛提供奖金或奖品,这不仅能给予学生经济上的奖励,还能增强其成就感和自信心。 荣誉证书或奖状可以证明学生的成就,对个人品牌建设有积极作用。 创新与研究: 参加比赛可以激发学生的创新思维,推动科研项目的开展,有时甚至能促成学术论文的发表。 个人成长: 在准备和参加比赛的过程中,学生将面临压力与挑战,这有助于培养良好的心理素质和抗压能力。 自我挑战和克服困难的经历对个人成长有着深远的影响。 综上所述,参加计算机领域的比赛对于学生来说是一个全面发展的平台,不仅可以提升专业技能,还能增强团队协作、沟通、解决问题的能力,并为未来的职业生涯奠定坚实的基础。
对于计算机专业的学生而言,参加各类比赛能够带来多方面的益处,具体包括但不限于以下几点: 技能提升: 参与比赛促使学生深入学习和掌握计算机领域的专业知识与技能,如编程语言、算法设计、软件工程、网络安全等。 比赛通常涉及实际问题的解决,有助于将理论知识应用于实践中,增强问题解决能力。 实践经验: 大多数比赛都要求参赛者设计并实现解决方案,这提供了宝贵的动手操作机会,有助于积累项目经验。 实践经验对于计算机专业的学生尤为重要,因为雇主往往更青睐有实际项目背景的候选人。 团队合作: 许多比赛鼓励团队协作,这有助于培养学生的团队精神、沟通技巧和领导能力。 团队合作还能促进学生之间的知识共享和思维碰撞,有助于形成更全面的解决方案。 职业发展: 获奖经历可以显著增强简历的吸引力,为求职或继续深造提供有力支持。 某些比赛可能直接与企业合作,提供实习、工作机会或奖学金,为学生的职业生涯打开更多门路。 网络拓展: 比赛是结识同行业人才的好机会,可以帮助学生建立行业联系,这对于未来的职业发展非常重要。 奖金与荣誉: 许多比赛提供奖金或奖品,这不仅能给予学生经济上的奖励,还能增强其成就感和自信心。 荣誉证书或奖状可以证明学生的成就,对个人品牌建设有积极作用。 创新与研究: 参加比赛可以激发学生的创新思维,推动科研项目的开展,有时甚至能促成学术论文的发表。 个人成长: 在准备和参加比赛的过程中,学生将面临压力与挑战,这有助于培养良好的心理素质和抗压能力。 自我挑战和克服困难的经历对个人成长有着深远的影响。 综上所述,参加计算机领域的比赛对于学生来说是一个全面发展的平台,不仅可以提升专业技能,还能增强团队协作、沟通、解决问题的能力,并为未来的职业生涯奠定坚实的基础。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值