ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

reentrantlock公平锁与非公平锁对比

2021-09-15 18:59:21  阅读:180  来源: 互联网

标签:return nextc int reentrantlock state 线程 公平 与非 final


先说结论:非公平锁加锁时先参与锁竞争,如果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

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有