ReentrantLockソースベースワークフローの理解

25180 ワード

ReentrantLockとsynchronizedはjdk 1にある.8バージョン以降のパフォーマンスはほぼ同じで、synchronizedは優れていますが、synchronizedは割り込みとタイムアウトをサポートしていません.つまり、synchronizedによってブロックされると、リソースを取得できないままブロックされ、中断しても役に立たないため、同時システムのパフォーマンスに大きな影響を与えます.ロックは割り込みとタイムアウトをサポートし、試行メカニズムのロック取得もサポートし、synchronizedをよく拡張しているので、柔軟性からlockはsynchronizedより明らかに優れている.
きほんほうしき
//  
// boolean fair  
ReentrantLock(boolean fair)

//  , 
void lock();
//  
void unlock();
//  
void lockInterruptibly() throws InterruptedException; 
//  , 
boolean tryLock();
//  , timeout 
boolean tryLock(long timeout, TimeUnit unit) throws InterruptedException;

フラットロック


錠をかける
final void lock() {
    acquire(1);
}

public final void acquire(int arg) {
    //  
    if (!tryAcquire(arg) &&
        // addWaiter    ( ) 
        // acquireQueued      ,  LockSupport.park(this)
        acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
        selfInterrupt();
}
// 
protected final boolean tryAcquire(int acquires) {
    final Thread current = Thread.currentThread();
    int c = getState();
    if (c == 0) { 
        //  
        // hasQueuedPredecessors  ( ) true:  , false:  
        if (!hasQueuedPredecessors() &&
            //   CAS  
            compareAndSetState(0, acquires)) {
            //  
            setExclusiveOwnerThread(current);
            return true;
        }
    }
    //  
    //  
    else if (current == getExclusiveOwnerThread()) {
        //     c + 1 ( )
        int nextc = c + acquires;
        if (nextc < 0)
            throw new Error("Maximum lock count exceeded");
        setState(nextc); //  
        return true;
    }
    return false;
}

//  
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 (;;) { 
            //  prev
            final Node p = node.predecessor();
            //   prev    
            if (p == head && tryAcquire(arg)) {
                setHead(node);
                p.next = null; // help GC
                failed = false;
                return interrupted;
            }
            //   park
            if (shouldParkAfterFailedAcquire(p, node) &&
                parkAndCheckInterrupt()) //   LockSupport.park(this);
                interrupted = true;
        }
    } finally {
        if (failed)
            cancelAcquire(node);
    }
}

リリースロック
public final boolean release(int arg) {
    //  
    if (tryRelease(arg)) {
        Node h = head;
        //     head   unpark  
        if (h != null && h.waitStatus != 0)
            unparkSuccessor(h);
        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;
    //   c == 0    
    if (c == 0) {
        free = true;
        //  
        setExclusiveOwnerThread(null);
    }
    setState(c);
    return free;
}

ノンフェアロック

final void lock() {
    //    ( )
    if (compareAndSetState(0, 1))
        //    
        setExclusiveOwnerThread(Thread.currentThread());
    else
        //  
        acquire(1);
}
protected final boolean tryAcquire(int acquires) {
    return nonfairTryAcquire(acquires);
}

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