欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

ReetranLock 源码解析

程序员文章站 2022-06-20 20:29:30
...

ReetranLock 类

1. 方法含义

方法 说明
lock() 阻塞的获得锁
tryLock() 非阻塞式获取锁
unlock() 释放锁
newCondition()
tryLock(long timeout, TimeUnit unit)

2. 方法解析

public void lock() {
    // 直接调用同步器的lock()
    sync.lock();
}
/** 
 * 非阻塞式获取锁
 */
public boolean tryLock() {
    // 直接调用非公平锁的获锁方法
    return sync.nonfairTryAcquire(1);
}

public boolean tryLock(long timeout, TimeUnit unit)
        throws InterruptedException {
    return sync.tryAcquireNanos(1, unit.toNanos(timeout));
}


1. 队列同步器

1.1 队列同步器中的锁操作
public abstract class AbstractQueuedSynchronizer
    extends AbstractOwnableSynchronizer
    implements java.io.Serializable {
	
    // 阻塞式获取锁
    public final void acquire(int arg) {
        /*
        1. 尝试非阻塞是获取锁,
        2. 获取锁失败,addWaiter(Node.EXCLUSIVE),将线程添加到等待队列
        3. 添加成功,自旋于 acquireQueued()
        */
        if (!tryAcquire(arg) &&
            acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
            selfInterrupt();
    }
    
    // 自旋,直到获取到锁
    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);
                    // 去点前一个结点的next引用
                    p.next = null; // help GC
                    failed = false;
                    return interrupted;
                }
                if (shouldParkAfterFailedAcquire(p, node) &&
                    parkAndCheckInterrupt())
                    interrupted = true;
            }
        } finally {
            // 如果faile等于true,当前节点取消等待
            if (failed)
                cancelAcquire(node);
        }
    }
    
    
    
}
1.2 队列同步器中的等待队列操作
// 添加等待线程
private Node addWaiter(Node mode) {
    // 创建节点
    Node node = new Node(Thread.currentThread(), mode);
    // 获取等待队列尾节点
    Node pred = tail;
    // 尾节点不为空,即等待队列不为空
    if (pred != null) {
        node.prev = pred;
        // 使用 CAS 重置尾节点
        if (compareAndSetTail(pred, node)) {
            // 重置成功,将尾节点的next指针指向本节点
            pred.next = node;
            return node;
        }
    }
    // 若尾节点为空或CAS失败
    enq(node);
    return node;
}
  
// 插入线程到等待队列,自旋直到插入成功
private Node enq(final Node node) {
    // 无限循环知道 cas 成功
    for (;;) {
        Node t = tail;
        if (t == null) {
            // CAS 设置头节点
            if (compareAndSetHead(new Node()))
                // 头节点设置成功则设置尾节点
                tail = head;
        } else {	// 等待队列不为空
            node.prev = t;
            // CAS 设置尾节点
            if (compareAndSetTail(t, node)) {
                // CAS 成功则将前尾节点的next指向当前节点
                t.next = node;
                return t;
            }
        }
    }
}
1.3 节点取消等待
private void cancelAcquire(Node node) {
    if (node == null)
        return;
    // 将当前节点绑定的线程设置为空
    node.thread = null;

    // 获取前节点
    Node pred = node.prev;
    // 如果前节点的等待状态大于 0 ,不断踢出队列
    while (pred.waitStatus > 0)
        // pred = pred.prev
        // node.prev = pred
        node.prev = pred = pred.prev;
    Node predNext = pred.next;
    // 设置当前节点的等待状态,将当前节点设置为取消等待状态
    node.waitStatus = Node.CANCELLED;
    // 如果当前节点是尾节点,CAS设置尾节点为前节点
    if (node == tail && compareAndSetTail(node, pred)) {
        // 将前节点的next节点设置为空
        compareAndSetNext(pred, predNext, null);
    } else {
        int ws;
        /*
        判断条件
        1. 前节点不是头节点
        2. 前节点的状态是SIGNAL或者状态值小于0且将其CAS设置为SIGNAL状态成功
        3. 前节点绑定的线程不为空
        */
        if (pred != head &&
            ((ws = pred.waitStatus) == Node.SIGNAL ||
             (ws <= 0 && compareAndSetWaitStatus(pred, ws, Node.SIGNAL))) &&
            pred.thread != null) {
            // 获取当前节点的next节点
            Node next = node.next;
            // 如果next不为空且不是处于取消等待状态
            if (next != null && next.waitStatus <= 0)
                // 将前节点的next节点设置为next
                compareAndSetNext(pred, predNext, next);
        } else {
            unparkSuccessor(node);
        }
        node.next = node; // help GC
    }
}
 
private void unparkSuccessor(Node node) {
    int ws = node.waitStatus;
    if (ws < 0)
        // 如果等待状态小于 0, 将其等待状态设置为 0 (初始化状态)
        compareAndSetWaitStatus(node, ws, 0);
    // 查看其next节点
    Node s = node.next;
    // 如果s为空或者为取消等待状态
    if (s == null || s.waitStatus > 0) {
        s = null;
        //
        for (Node t = tail; t != null && t != node; t = t.prev)
            if (t.waitStatus <= 0)
                s = t;
    }
    if (s != null)
        LockSupport.unpark(s.thread);
}

2. sync 内部类

ReentrantLock 内部维护了一个队列同步器继承于 AbstractQueuedSynchronizer ,lock的操作都是基于队列同步器进行的

1.Sync类实现

abstract static class Sync extends AbstractQueuedSynchronizer {
        private static final long serialVersionUID = -5179523762034025860L;

    	// 抽象声明lock方法,具体由实现类(公平锁和非公平锁实现)
        abstract void lock();

   		// 非公平锁的非阻塞获取锁的具体实现
        final boolean nonfairTryAcquire(int acquires) {
            // 获取当前线程
            final Thread current = Thread.currentThread();
            // 获取同步状态
            int c = getState();
            if (c == 0) {
                // 如果同步状态为 0
                // 使用CAS更新同步状态为 1 
                if (compareAndSetState(0, acquires)) {
                    // 将当前线程设置为获得锁的线程
                    setExclusiveOwnerThread(current);
                    return true;
                }
            }
            // 如果同步状态不为0
            // 且或得所得线程为当前线程
            else if (current == getExclusiveOwnerThread()) {
                // 同步状态+1
                int nextc = c + acquires;
                if (nextc < 0) // overflow
                    throw new Error("Maximum lock count exceeded");
                setState(nextc);
                return true;
            }
            // 返回获取失败
            return false;
        }

    	// 释放锁
        protected final boolean tryRelease(int releases) {
            // 查询状态并-1
            int c = getState() - releases;
            // 如果释放锁的线程非获得所得线程,抛出异常
            if (Thread.currentThread() != getExclusiveOwnerThread())
                throw new IllegalMonitorStateException();
            boolean free = false;
            // 如果同步状态为0
            if (c == 0) {
                free = true;
                // 将获得锁线程设置为null
                setExclusiveOwnerThread(null);
            }
            // 重设同步状态
            setState(c);
            // 如果锁已经完全释放,返回true
            return free;
        }

    	// 判断当前线程是否为获得此锁
        protected final boolean isHeldExclusively() {
            return getExclusiveOwnerThread() == Thread.currentThread();
        }

        final ConditionObject newCondition() {
            return new ConditionObject();
        }
		// 获取当前持有锁的线程
        final Thread getOwner() {
            return getState() == 0 ? null : getExclusiveOwnerThread();
        }
		// 获取重入次数
        final int getHoldCount() {
            return isHeldExclusively() ? getState() : 0;
        }
		// 判断锁是否已被使用
        final boolean isLocked() {
            return getState() != 0;
        }

        private void readObject(java.io.ObjectInputStream s)
            throws java.io.IOException, ClassNotFoundException {
            s.defaultReadObject();
            setState(0); // reset to unlocked state
        }
    }

2. ReentrantLock 提供了公平锁和非公平锁

FairSyncNonfairSync 均继承于 Sync, 实现了不同的锁竞争机制

2.1 公平锁

按照时间先后顺序获取锁

static final class FairSync extends Sync {
    private static final long serialVersionUID = -3000897897090466540L;
    
    final void lock() {
        acquire(1);
    }
    /**
     * 非阻塞式的获取公平锁
     */
    protected final boolean tryAcquire(int acquires) {
        final Thread current = Thread.currentThread();
        int c = getState();
        if (c == 0) {
            /*
            hasQueuedPredecessors(),判断是否由线程在等待获得锁
            如果没有等待线程,使用CAS设置同步状态
            */
            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;
    }
}
2.2 非公平锁

谁先拿到就是谁的

static final class NonfairSync extends Sync {
	private static final long serialVersionUID = 7316153563782823691L;
    // 阻塞时获取锁
    final void lock() {
        // 如果同步状态为 0 ,将其设置为 1
        if (compareAndSetState(0, 1))
            // CAS 成功,则获得锁
            setExclusiveOwnerThread(Thread.currentThread());
        else
            // CAS 不成功调用 AbstractQueuedSynchronizer 的 acquire()
            acquire(1);
    }
		
    // 非阻塞式获取得公平锁,调用 sync 中的 nonfairTryAcquire()
    protected final boolean tryAcquire(int acquires) {
        return nonfairTryAcquire(acquires);
    }
}
相关标签: 源码解析