美文网首页Java 杂谈
java锁机制分类以及实现原理剖析(1)--公平锁与非公平锁

java锁机制分类以及实现原理剖析(1)--公平锁与非公平锁

作者: 乐乐J | 来源:发表于2019-05-05 11:46 被阅读0次

    我们最早接触java线程锁,其实也就是syncronized和ReentrantLock,ReentrantLock作为Lock的一个实现,其实构造时,也分为公平锁与非公平锁之分。
    先看源码:

     /**
         * Creates an instance of {@code ReentrantLock} with the
         * given fairness policy.
         *
         * @param fair {@code true} if this lock should use a fair ordering policy
         */
        public ReentrantLock(boolean fair) {
            sync = fair ? new FairSync() : new NonfairSync();
        }
    

    这一部分就是ReentrantLock的构造方法,传入的参数不同构造的锁类型就将不同。
    下面先看看一下公平锁的实现,源码如下:

    /**
         * Sync object for fair locks
         */
        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)
                        throw new Error("Maximum lock count exceeded");
                    setState(nextc);
                    return true;
                }
                return false;
            }
        }
    

    然后再贴出非公平锁的实现源码:

     /**
         * Sync object for non-fair locks
         */
        static final class NonfairSync extends Sync {
            private static final long serialVersionUID = 7316153563782823691L;
    
            /**
             * Performs lock.  Try immediate barge, backing up to normal
             * acquire on failure.
             */
            final void lock() {
                if (compareAndSetState(0, 1))
                    setExclusiveOwnerThread(Thread.currentThread());
                else
                    acquire(1);
            }
    
            protected final boolean tryAcquire(int acquires) {
                return nonfairTryAcquire(acquires);
            }
        }
    

    先从概念上,我的理解是:
    公平锁: 每个等待的线程首先他们获取锁的机会是公平的,那么怎么保证他们是公平的呢?只能是根据申请锁的顺序来保证,那顺序又如何保证呢,必然是有一个类似队列的数据结构来序列化等待的线程。
    非公平锁:从字面意思上理解,每个等待的线程获取锁的机会是不公平的,那他们如何获取锁呢?显然获取锁的时候就该八仙过海,各显神通了,必然会导致有些能力差的线程抢不到锁。
    带着这些概念上的理解与思路我们开始重读源码。先从non-fair locks 开始。

    非公平锁

    我们来逐行分析:
    1.首先是对象序列化时候的UID。
    2.lock()是一个构建锁的方法,tryAcquire()是一个获取锁的方法。
    3.先看lock()方法,会先去执行本地CAS算法,看看当前锁的状态是不是0,是0的话就改为1,那么就给当前线程排它的权限,也就是对当前线程操作的资源加上了锁。如果CAS算法结果不成立,然后会去获取锁。

    1. tryAcquire()尝试获取锁方法。
    /**
             * Performs non-fair tryLock.  tryAcquire is implemented in
             * subclasses, but both need nonfair try for trylock method.
             */
            final boolean nonfairTryAcquire(int acquires) {
                final Thread current = Thread.currentThread();
                int c = getState();
                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;
                }
                return false;
            }
    

    如果当前资源不在同步状态,compareAndSetState(0, acquires) CAS算法看状态, setExclusiveOwnerThread(current);设置当前线程加锁。如果当前线程有锁就更新锁状态。

    公平锁

    与非公平锁一样,提供lock()与tryAcquire()方法,不一样的是fair lock多了一个对等待线程队列的判断,当前线程是否处在最前。

    相关文章

      网友评论

        本文标题:java锁机制分类以及实现原理剖析(1)--公平锁与非公平锁

        本文链接:https://www.haomeiwen.com/subject/xvhcoqtx.html