JUC.ReetrantLock

63 阅读1分钟

JUC.ReetrantLock

公平锁尝试获取锁

protected final boolean tryAcquire(int acquires) {
    // 当前线程  
    final Thread current = Thread.currentThread();
    // 获取锁情况  
    int c = getState();
    // 没人锁  
    if (c == 0) {
        // 是头节点的下一个节点或者首节点  
        // 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;
}

非公平锁尝试获取锁

final boolean nonfairTryAcquire(int acquires) {
    // 当前线程  
    final Thread current = Thread.currentThread();
   // 获取锁情况
    int c = getState();
    // 没人锁
    if (c == 0) {
        // cas设置持有锁数量
        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;
}

## 增加当前节点
追加当前线程到队列
``` java
acquireQueued(addWaiter(Node.EXCLUSIVE), arg)

节点定义

static final class Node {
    /** Marker to indicate a node is waiting in shared mode */
    static final Node SHARED = new Node();
    /** Marker to indicate a node is waiting in exclusive mode */
    static final Node EXCLUSIVE = null;

    Node nextWaiter;
    volatile Thread thread;

    Node(Thread thread, Node mode) {     // Used by addWaiter
        this.nextWaiter = mode;
        this.thread = thread;
    }

增加到双向链表尾部节点

private Node addWaiter(Node mode) {
    Node node = new Node(Thread.currentThread(), mode);
    // Try the fast path of enq; backup to full enq on failure
    Node pred = tail;
    if (pred != null) {
        node.prev = pred;
        if (compareAndSetTail(pred, node)) {
            pred.next = node;
            return node;
        }
    }
    enq(node);
    return node;
}

尝试排队

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

            // 获取失败则cas更改状态等待前一个节点状态变更  
            // 暂停中断当前线程
            if (shouldParkAfterFailedAcquire(p, node) &&
                parkAndCheckInterrupt())
                interrupted = true;

        }

    } finally {
        if (failed)
            // 取消节点
            cancelAcquire(node);

    }

}

获取锁失败检测是否可以park休眠

private static boolean shouldParkAfterFailedAcquire(Node pred, Node node) {
    int ws = pred.waitStatus;
    // 前节点已经唤醒  
    if (ws == Node.SIGNAL)
        return true;
    // 前节点取消,则递归前前节点  
    if (ws > 0) {
        do {
            node.prev = pred = pred.prev;
        } while (pred.waitStatus > 0);
        pred.next = node;
    } 
    // 唤醒前节点的休眠  
    else {
        compareAndSetWaitStatus(pred, ws, Node.SIGNAL);
    }
    return false;
}

暂停当前线程

private final boolean parkAndCheckInterrupt() {
    LockSupport.park(this);
    return Thread.interrupted();
}

独占同步器-线程维度

public abstract class AbstractOwnableSynchronizer
    implements java.io.Serializable {
    private static final long serialVersionUID = 3737899427754241961L;  

    protected AbstractOwnableSynchronizer() { }

    private transient Thread exclusiveOwnerThread;

    protected final void setExclusiveOwnerThread(Thread thread) {
        exclusiveOwnerThread = thread;
    }

    protected final Thread getExclusiveOwnerThread() {
        return exclusiveOwnerThread;
    }
}

常见问题

重入如何实现

通过state维护进入锁的线程数,重入情况累加state

公平非公平怎么实现

通过双向链表维护线程执行的先后关系,公平则必须是头节点的第二节点才能执行