变是永远不变的......

希望和大家交流

Reentrantlock源码解析

Reentrantlock及可重入锁,读源码首先要看下它的outline:
这里写图片描述
其核心就是公平锁fairSync和非公平送NonFairSync
我们可以看到这两个锁有共同的方法:lock();

  1. fairSync
 final void lock() {
            acquire(1);
        }
  1. NonfairSync
final void lock() {
            if (compareAndSetState(0, 1))
                setExclusiveOwnerThread(Thread.currentThread());
            else
                acquire(1);
        }

在资源没有被占用的情况下:

非公平锁是: 先state+1,然后直接得到锁,
而公平锁则是: 先尝试去获取锁,如果得到了锁则state+1.

如果是同一线程,再次申请锁

两种锁,表现基本一致,可以参考下面的代码块. (只是这段代码块在不同函数中)
fairSync:

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;
        }

NonfairSync

protected final boolean tryAcquire(int acquires) {
            return nonfairTryAcquire(acquires);
        }

如果是不同线程申请锁:

从业务逻辑来看,公平锁和非公平锁唯一的区别就是需要判断当前线程是不是链表头.但是一直有一点不明白的,在c==0的情况下, 不是就可以说明已经是表头了吗? 为什么还要检查 isFirst(current). compareAndSetState(0, acquires) 也可以保证在并发的情况下只有state=0才能获取锁.

总结

非公平锁,和公平锁只有在state=0的时候,业务逻辑不一样.
在stage=0的时候,非公平锁是直接获取锁,没有维护等待队列.
在stage=0的时候, 公平锁依然需要检查当前线程是否是等待队列的第一个.

阅读更多
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/wangdan199112/article/details/51547344
文章标签: Reentrantl
上一篇线程同步详解
下一篇NIO之Buffer channel
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

关闭
关闭