其他分享
首页 > 其他分享> > reentrantlock公平锁与非公平锁对比

reentrantlock公平锁与非公平锁对比

作者:互联网

先说结论:非公平锁加锁时先参与锁竞争,如果state为0,则获取到锁。如果不为0,分三种情况。第一种情况,state为0(距离刚刚判断已经过去一会儿了,刚刚不为零,现在可能为零),获取到锁。第二种情况,state不为0,但是持有锁的线程是自己,也就是二次加锁,此时state会加一。第三种情况,state不为0并且持有锁的线程也不是自身,则将当前线程加入到一个双向链表队列中。

公平锁加锁时,分三种情况。第一如果state为0,判断队列中是否有线程比自己先来,如果有,则将自己加入队尾,如果没有则获取到锁。第二种情况,state不为0,但是如果当前持有锁的线程是自己,就进行二次加锁。第三种情况,state不为0并且持有锁的线程也不是自身,则将当前线程加入到队尾。

下面来看一下,源码实现

非公平锁:

final void lock() {
            //先参与锁竞争
            if (compareAndSetState(0, 1))
                setExclusiveOwnerThread(Thread.currentThread());
            else
            //竞争失败在执行acquire方法
                acquire(1);
    }



//这里分为三种情况 
1.state为0 
2.当前线程持有锁  
3.加入阻塞队列队尾。
前两种情况在tryAcquire中实现,第三种情况在acquireQueued中实现 

public final void acquire(int arg) {
    if (!tryAcquire(arg) &&
            acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
            selfInterrupt();
    }



公平锁:

//公平锁相对于非公平锁少了一次锁竞争
final void lock() {
            acquire(1);
        }

public final void acquire(int arg) {
        if (!tryAcquire(arg) &&
            acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
            selfInterrupt();
    }

同样分三种情况时,state为0,两种锁的处理方法也不同,开头我们总结的时候用文字描述了,下面我们从代码的层面描述一下。

final boolean nonfairTryAcquire(int acquires) {
            final Thread current = Thread.currentThread();
            int c = getState();
            //非公平锁state为0时,直接cas获取锁
            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;
        }

protected final boolean tryAcquire(int acquires) {
            final Thread current = Thread.currentThread();
            int c = getState();
            //公平锁state为0时,判断队头线程是否比当前线程等待时间长
            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;
        }

标签:return,nextc,int,reentrantlock,state,线程,公平,与非,final
来源: https://blog.csdn.net/sheng_xinjun/article/details/120314350