C/C++教程

ReentrantLock源码解析

本文主要是介绍ReentrantLock源码解析,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

ReentrantLock继承,组合。ReentrantLock实现了Lock接口,持有Sync实例,Sync的抽象父类是AbstractQueuedSynchronizer(以下称为AQS)AQS继承自AbstractOwnableSynchronizer(以下称之为AOS)AOS中只有一个成员变量Thread,当前持有锁的线程。

Sync有两个实现分别为NonfairSync非公平锁,FairSync公平锁。无参构造器默认为非公平锁,可以通过有参构造使用公平锁。

class ReentrantLock implements Lock, java.io.Serializable{
    private final Sync sync;
    abstract static class Sync extends AbstractQueuedSynchronizer{}
    static final class NonfairSync extends Sync{}
    static final class FairSync extends Sync{}      
}

public abstract class AbstractQueuedSynchronizer extends AbstractOwnableSynchronizer implements java.io.Serializable{}

public abstract class AbstractOwnableSynchronizer implements java.io.Serializable{
    private transient Thread exclusiveOwnerThread;
}
  public ReentrantLock() {
        sync = new NonfairSync();
    }
 public ReentrantLock(boolean fair) {
        sync = fair ? new FairSync() : new NonfairSync();
    }

加锁代码,先看公平锁,假设现在只有一条线程获取锁,还原获取锁成功的步骤。

 public void lock() {
        sync.lock();
    }
final void lock() {
    acquire(1);//AQS中
}
//AQS中
public final void acquire(int arg) {
        if (!tryAcquire(arg) &&
            acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
            selfInterrupt();
    }
        protected final boolean tryAcquire(int acquires) {//入参1,尝试获取锁操作。
            final Thread current = Thread.currentThread();//当前线程。
            int c = getState();//AQS中的变量,默认为0,表示锁未被占用。
            if (c == 0) {//能进来说明当前锁未被占用。
                if (!hasQueuedPredecessors() &&
                    compareAndSetState(0, acquires)) {
                    setExclusiveOwnerThread(current);//把当前线程设置到AOS中,占有锁成功。
                    return true;//返回成功。
                }
            }
            else if (current == getExclusiveOwnerThread()) {//getExclusiveOwnerThread从AOS中获取当前持有锁的线程是不是当前线程。
                int nextc = c + acquires;//重入锁+1。
                if (nextc < 0)
                    throw new Error("Maximum lock count exceeded");
                setState(nextc);//设置锁占用标记。
                return true;//返回成功。
            }
            return false;//返回失败。
        }
//AQS
public final boolean hasQueuedPredecessors() {
        Node t = tail; //将等待获取锁的线程封装到Node中,在AQS中有尾部,头部两个链表指针。
        Node h = head;
        Node s;
     //h!=t表示链表有元素,h.next==null表示链表中只有一个元素,链表中唯一的元素不是当前线程。
        return h != t &&((s = h.next) == null || s.thread != Thread.currentThread());
}

//AQS
protected final boolean compareAndSetState(int expect, int update) {
        //使用Unsafe设置成员变量state为1,不了解Unsafe的可以看上一篇博客。
        return unsafe.compareAndSwapInt(this, stateOffset, expect, update);
}

//AOS
protected final void setExclusiveOwnerThread(Thread thread) {
        exclusiveOwnerThread = thread;//设置当前线程为独占线程
}

还原锁获取失败的步骤。

final void lock() {
     acquire(1);
}
public final void acquire(int arg) {
        if (!tryAcquire(arg) &&
            acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
            selfInterrupt();
}
 protected final boolean tryAcquire(int acquires) {
            final Thread current = Thread.currentThread();
            int c = getState();
            if (c == 0) {
                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;
}
    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;
                }
                if (shouldParkAfterFailedAcquire(p, node) &&
                    parkAndCheckInterrupt())
                    interrupted = true;
            }
        } finally {
            if (failed)
                cancelAcquire(node);
        }
    }

 

这篇关于ReentrantLock源码解析的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!