ReetrantLock独占锁解析

自由一定是相对的,只有自律的人,才能有自由。

首先看ReetrantLock的构造方法

public ReentrantLock(boolean fair) {
   sync = fair ? new FairSync() : new NonfairSync();
}

基于传入的boolean变量决定创建公平锁or非公平锁,sync是ReetrantLock的成员变量,并发包下的很多类都是以这种方式,存在一个成员变量sync,并有一个内部类sync继承自AQS(AbstractQueuedSynchronizer)抽象队列同步器

先看公平锁FairSync,调用lock方法

java.util.concurrent.locks.ReentrantLock#lock
java.util.concurrent.locks.ReentrantLock.FairSync#lock

final void lock() {
    acquire(1);
}

java.util.concurrent.locks.AbstractQueuedSynchronizer#acquire

public final void acquire(int arg) {
	// 尝试获取锁,如果获取失败,尝试以独占类型加到队列中
    if (!tryAcquire(arg) &&
        acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
        selfInterrupt();
}

java.util.concurrent.locks.ReentrantLock.FairSync#tryAcquire

protected final boolean tryAcquire(int acquires) {
	// 拿到当前线程
    final Thread current = Thread.currentThread();
    // 获取state
    int c = getState();
    // 如果为0,表示没有任何人获取锁,可以进行加锁
    if (c == 0) {
    	// 如果等待队列中没有等待的线程(表明上个拿到锁的线程刚执行完,并且有其他线程正在等待获取锁)并且使用cas设置状态成功(成功获取到锁)
        if (!hasQueuedPredecessors() &&
            compareAndSetState(0, acquires)) {
            // 设置独占线程为当前线程
            setExclusiveOwnerThread(current);
            return true;
        }
    }
    // 如果当前线程是锁的独占线程,state加本次获取次数并返回获取成功
    else if (current == getExclusiveOwnerThread()) {
        int nextc = c + acquires;
        if (nextc < 0)
            throw new Error("Maximum lock count exceeded");
        setState(nextc);
        return true;
    }
    return false;
}

java.util.concurrent.locks.AbstractQueuedSynchronizer#addWaiter
// 入队列
private Node addWaiter(Node mode) {
    Node node = new Node(Thread.currentThread(), mode);
    Node pred = tail;
    // 如果队列的尾节点不为空,则将入队节点的前驱节点指向之前的尾节点,并通过cas设置尾节点为新入队的节点,设置成功后,将之前的尾节点的下个节点设置为新入队的节点
    if (pred != null) {
        node.prev = pred;
        if (compareAndSetTail(pred, node)) {
            pred.next = node;
            return node;
        }
    }
    // 如果不满足,执行入队方法
    enq(node);
    return node;
}

java.util.concurrent.locks.AbstractQueuedSynchronizer#enq
// 入队
private Node enq(final Node node) {
	// 死循环多次尝试
    for (;;) {
        Node t = tail;
        if (t == null) { // 如果tail为空(队列的初始状态)
        	// 通过cas创建初始节点,设置成功后将尾节点也指向头结点
            if (compareAndSetHead(new Node()))
                tail = head;
        } else { // 如果尾节点不为空,设置新节点的前驱节点为尾节点,并通过cas设置尾节点为新入队的节点,设置成功后,将之前的尾节点的下个节点设置为新入队的节点
            node.prev = t;
            if (compareAndSetTail(t, node)) {
                t.next = node;
                return t;
            }
        }
    }
}

我们来看下非公平锁的lock方法

java.util.concurrent.locks.ReentrantLock.NonfairSync#lock

final void lock() {
	// 可以看出跟公平锁的区别就是,非公平锁的lock会一上来就尝试获取锁,如果获取成功,设置独占线程为当前线程,即非公平锁可以插队
    if (compareAndSetState(0, 1))
        setExclusiveOwnerThread(Thread.currentThread());
    else
        acquire(1);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值