死磕源码系列(ReentrantLock)

前言

  • 在高并发领域,ReentrantLock有着普遍的用处,防止多线程带来的并发问题
  • 对于源码,不少人和我一开始同样都以为很是神秘
  • 此次我将对ReentrantLock进行全方面的揭秘

核心

  • AbstractQueuedSynchronizer
    • AQS是JDK实现的CAS同步器。里面的核心是state和两个node
    • state标识同步器如今的状态,node做为队列串联同步器中的节点
    • 使用volatile保证参数的可见性
volatile Node prev;
volatile Node next;
private volatile int state;

总体结构

  • ReentrantLock 调用内部类Sync,Sync继承AbstractQueuedSynchronizer

总体流程

  • ReentrantLock调用内部类Sync的acquire方法,底层走的是AbstractQueuedSynchronizer,AbstractQueuedSynchronizer会尝试获取锁,获取失败以后会加入队列中,而后节点自旋去获取锁,一旦成功就将本身的节点至于头部,而后退出。
  • cas实现(compareAndSet)。jdk9以前使用的是unsafe,jsk9以后使用的是varHandler。

核心代码

AQS:node

public final void acquire(int arg) {
        if (!tryAcquire(arg) &&
            acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
            selfInterrupt();
    }
  • tryAcquire是第一次尝试获取所,公平锁和非公平锁的区别只是判断本身节点是否除了head节点外仍是在本身前面的,校验的是公平锁,不校验的是非公平锁
  • addWaiter是节点加入到队列中
  • acquireQueued里面执行的就是自旋操做
final boolean acquireQueued(final Node node, int arg) {
        boolean failed = true;
        try {
            boolean interrupted = false;
            //自旋开始
            for (;;) {
                final Node p = node.predecessor();
                //尝试开始获取锁
                if (p == head && tryAcquire(arg)) {
                    setHead(node);
                    p.next = null; // help GC
                    failed = false;
                    return interrupted;
                }
                if (shouldParkAfterFailedAcquire(p, node) &&
                    parkAndCheckInterrupt())
                    interrupted = true;
            }
        } finally {
            if (failed)
                cancelAcquire(node);
        }
    }

释放锁

protected final boolean tryRelease(int releases) {
            int c = getState() - releases;
            if (Thread.currentThread() != getExclusiveOwnerThread())
                throw new IllegalMonitorStateException();
            boolean free = false;
            if (c == 0) {
                free = true;
                setExclusiveOwnerThread(null);
            }
            setState(c);
            return free;
        }
相关文章
相关标签/搜索