JUC代码浅析[2]——基于AQS的锁ReentrantLock

JUC代码浅析[2]——基于AQS的锁ReentrantLock

         ReentrantLock是使用比较普遍的一个可重入锁,它是互斥的,一个锁只能被一个线程占有。它的方法基本都是委托给继承AQSSync实现的。其中Sync有两种实现,公平和非公平。Sync使用state(通过AQS暴露的getStatesetState方法)保存线程的获取次数。总的策略为state次数为0时可以获得锁。大于0时,如果当前线程已经拥有该锁则可再次获得,否则进入AQS的调度逻辑(<JUC代码浅析——同步器AQS>中介绍)。下面为非公平ReentrantLockNonfairSync实现,

        final void lock() {

            if (compareAndSetState(0, 1))

                setExclusiveOwnerThread(Thread.currentThread());

            else

                acquire(1);

        }

如果state次数为0的话,获得成功并设置当前线程为锁的拥有者。

否则进入AQS调度,acquire(1)方法使用tryAcquire尝试获得,这里重载的tryAcquire调用的是nonfairTryAcquire方法

        final boolean nonfairTryAcquire(int acquires) {

            final Thread current = Thread.currentThread();

            int c = getState();

           //如果当前重进入数为0,有机会取得锁

            if (c == 0) {

           //获得成功并设置当前线程为锁的拥有者

                if (compareAndSetState(0, acquires)) {

                    setExclusiveOwnerThread(current);

                    return true;

                }

            }

       //如果当前线程已经拥有该锁则可再次获得

            else if (current == getExclusiveOwnerThread()) {

                int nextc = c + acquires;

                if (nextc < 0) // overflow

                    throw new Error(“Maximum lock count exceeded”);

                setState(nextc);

                return true;

            }

       //都不满足,则进入AQS队列等待调度

            return false;

        }

 

公平ReentrantLockFairSync实现

protected final boolean tryAcquire(int acquires) {

            final Thread current = Thread.currentThread();

            int c = getState();

       //如果当前重进入数为0,有机会取得锁

            if (c == 0) {

           //如果当前线程是第一个等待者,获得成功并设置当前线程为锁的拥有者

                if (isFirst(current) &&

                    compareAndSetState(0, acquires)) {

                    setExclusiveOwnerThread(current);

                    return true;

                }

            }

       //如果当前线程已经拥有该锁则可再次获得

            else if (current == getExclusiveOwnerThread()) {

                int nextc = c + acquires;

                if (nextc < 0)

                    throw new Error(“Maximum lock count exceeded”);

                setState(nextc);

                return true;

            }

       //都不满足,则进入AQS队列等待调度

            return false;

        }

 

       fairSyncNonfairSynctryRelease方法是同一个,比较简单,就是改变一下state次数,如果需要的话把拥有者线程置为null

        protected final boolean tryRelease(int releases) {

            int c = getState() – releases;

            if (Thread.currentThread() != getExclusiveOwnerThread())

                throw new IllegalMonitorStateException();

            boolean free = false;

            if (c == 0) {

                free = true;

                setExclusiveOwnerThread(null);

            }

            setState(c);

            return free;

        }

 

       公平和非公平的区别就在于,尝试进入的时候需要判断当前线程是否是队列的第一个,是第一个才能进入。这样AQS在调度的时候就会阻塞掉很多线程,性能差别就比较大。ReentrantLock只支持互斥模式,没有共享模式

 

    原文作者:JUC
    原文地址: https://blog.csdn.net/iteye_3559/article/details/82044980
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞