《Java源码分析》:ReentrantLock.lock 锁机制

《Java源码分析》:ReentrantLock.lock 锁机制

AbstractQueuedSynchronizer这个类真的很难也很复杂,是构建锁以及实现其他相关同步类的基础框架。本来是没有打算来研究下这个类,但是由于想了解锁机制,因此,不可避免的需要研究它。

但是这个类确实很难,自己看了几遍这个类也还是没有过多的看懂,本篇博文只能说是对自己看这个类的一点点理解和记录,若有错,请批评指正。

基本的思想是表现为一个同步器,支持下面两个操作:

1、获取锁:首先判断当前状态是否允许获取锁,如果是就获取锁,否则就阻塞操作或者获取失败,也就是说如果是独占锁就可能阻塞,如果是共享锁就可能失败。另外如果是阻塞线程,那么线程就需要进入阻塞队列。当状态位允许获取锁时就修改状态,并且如果进了队列就从队列中移除。

2、释放锁:这个过程就是修改状态位,如果有线程因为状态位阻塞的话就唤醒队列中的一个或者更多线程。

1、ReentrantLock类的lock()方法

由于锁Lock的实现都是委托给AbstractQueuedSynchronizer来实现的。因此,就将分析ReenterantLock类中如何获取锁和如何释放锁来理解AbstractQueuedSynchronizer的相关知识。

public void java.util.concurrent.locks.ReentrantLock.lock()

API文档对此方法的说明如下:

功能:获取锁。

如果该锁没有被另一个线程保持,则获取该锁并立即返回,并将锁的保持计数器设置为1.

如果当前线程已经保持该锁,则将保持计数加1,并且该方法立即返回。

如果该锁被另一个线程保持,则出于线程调度的目的,禁用该线程,并且在获得锁之前,该线程一直处于休眠状态,此时锁保持计数被设置为1.

从上面的文档可以看出ReentrantLock是可重入锁的实现。而内部是委托java.util.concurrent.locks.ReentrantLock.Sync.lock()实现的。

java.util.concurrent.locks.ReentrantLock.Sync是抽象类,有java.util.concurrent.locks.ReentrantLock.FairSync和java.util.concurrent.locks.ReentrantLock.NonfairSync两个实现,也就是常说的公平锁和不公平锁。

公平锁和非公平锁

如果获取一个锁是按照请求的顺序得到的,那么就是公平锁,否则就是非公平的。

在没有深入了解内部机制及实现之前,先了解下为什么会存在公平锁和非公平锁。

1、公平锁保证一个阻塞的线程最终能够获得锁,因为是有序的,所以总是可以按照请求的顺序获得锁。

2、不公平锁意味着后请求锁的线程可能在其前面排列的休眠线程恢复前拿到锁,这样就有可能提高并发的性能。这是因为通常情况下挂起的线程重新开始与它真正开始运行,二者之间会产生严重的延时。因此非公平锁就可以利用这段时间完成操作。这是非公平锁在某些时候比公平锁性能要好的原因之一。

二者在实现上的区别会在后面介绍,我们先从公平锁(FairSync)开始。ReentrantLock类中公平锁的源码如下。

    static final class FairSync extends Sync {
   
        private static final long serialVersionUID = -3000897897090466540L;

        final void lock() {
            acquire(1);//
        }

        /**
         * Fair version of tryAcquire.  Don't grant access unless
         * recursive call or no waiters or is first.
         */
        protected final boolean tryAcquire(int acquires) {
            final Thread current = Thread.currentThread();
            int c = getState();
            if (c == 0) {
                if (!hasQueuedPredecessors() &&
                    compareAndSetState(0, acquires)) {
                    setExclusiveOwnerThread(current);
                    return true;
                }
            }
            else if (current == getExclusiveOwnerThread()) {
                int nextc = c + acquires;
                if (nextc < 0)
                    
  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值