美文网首页
以ReentrantLock为例分析公平锁和非公平锁

以ReentrantLock为例分析公平锁和非公平锁

作者: enjoycc97 | 来源:发表于2019-06-27 16:49 被阅读0次
        ReentrantLock lock = new ReentrantLock();
        lock.lock();
        lock.unlock();

分析lock()

内部触发了Sync.lock(),Sync这个类有2个实现,FairSync和NonfailrSync,也就是公平锁和非公平锁的实现。在默认构造方法,可以看出来默认是非公平锁

 public ReentrantLock() {
        sync = new NonfairSync();
    }

非公平锁,锁机制

非公平锁,获取锁步骤,如果能将状态成功设置则设置当前线程为获取锁的线程,否则触发获取锁的尝试

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

进入acquire(1)

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

获取锁尝试失败,则进入等待队列排队

参考AQS里面 acquireQueued机制

公平锁获取

释放锁

protected final boolean tryAcquire(int acquires) {
            final Thread current = Thread.currentThread();
            int c = getState();
            if (c == 0) {
                if (!hasQueuedPredecessors() &&//公平锁体现在判断前置节点没有等待的线程才去加锁,也就是头结点后面没有节点,或者自己就是head才去加锁
                    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;
        }

释放锁

ReentrantLock.unlock触发的Sync.release()都是AQS继承的release(1)
也就是没有公平和非公平之分,尝试把状态减去1成功则唤醒当前线程

相关文章

网友评论

      本文标题:以ReentrantLock为例分析公平锁和非公平锁

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