ReentrantLock源码解析

ReentrantLock

构造函数:

public ReentrantLock() {
        sync = new NonfairSync();
}

加锁:

//ReentrantLock的lock方法
public void lock() {
        sync.lock();
}
//sync的lock方法,sync其实就是基于AQS实现的一个类
final void lock() {
    //如果CAS从0设为1成功,说明获取到锁
    if (compareAndSetState(0, 1))
        //将exclusiveOwnerThread变量设置为当前线程
        setExclusiveOwnerThread(Thread.currentThread());
    else
        //获取锁失败
        acquire(1);
}
public final void acquire(int arg) {
    //tryAcquire再次尝试获取锁,失败返回false
    //acquireQueued内有一个循环用于唤醒后tryAcquire
    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();
                //如果是队列第一个线程节点则tryAcquire,及尝试获取锁
                if (p == head && tryAcquire(arg)) {
                    //获取成功,设置为head
                    setHead(node);
                    p.next = null; // help GC
                    failed = false;
                    return interrupted;
                }
                //shouldParkAfterFailedAcquire将p设置为SIGNAL
                //parkAndCheckInterrupt将线程挂起
                if (shouldParkAfterFailedAcquire(p, node) &&
                    parkAndCheckInterrupt())
                    interrupted = true;
            }
        } finally {
            if (failed)
                cancelAcquire(node);
        }
    }

公平锁的tryAcquire

protected final boolean tryAcquire(int acquires) {
            final Thread current = Thread.currentThread();
            int c = getState();
            if (c == 0) {
            //hasQueuedPredecessors用于判断同步队列是否有节点,有的话新来的线程就不会去竞争锁,以达到公平的目的
                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;
}

非公平锁的tryAcquire

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

1、公平锁能保证:老的线程排队使用锁,新线程仍然排队使用锁。
2、非公平锁保证:老的线程排队使用锁;但是无法保证新线程抢占已经在排队的线程的锁

释放锁:

public void unlock() {
        sync.release(1);
}
public final boolean release(int arg) {
    //释放掉arg个state
        if (tryRelease(arg)) {
            Node h = head;
            if (h != null && h.waitStatus != 0)
                //唤醒同步队列的第一个线程节点,使其开始for循环,unparkSuccessor不再分析,和CountDownLatch一样
                unparkSuccessor(h);
            return true;
        }
        return false;
    }
protected final boolean tryRelease(int releases) {
    //state减去releases
    int c = getState() - releases;
    if (Thread.currentThread()                  !=getExclusiveOwnerThread())
        throw new IllegalMonitorStateException();
    boolean free = false;
    if (c == 0) {
        free = true;
        //将占用的线程设置为null
        setExclusiveOwnerThread(null);
    }
    setState(c);
    return free;
}

newCondition()分析:

final ConditionObject newCondition() {
            return new ConditionObject();
 }

调用等待方法

public final void await() throws InterruptedException {
    if (Thread.interrupted())
        throw new InterruptedException();
   //将此线程加入条件队列(等待队列),单向链表
    Node node = addConditionWaiter();
    //释放掉state,并唤醒同步队列的第一个线程节点
    int savedState = fullyRelease(node);
    int interruptMode = 0;
    //退出循环的条件:1.该节点在同步队列(即被其他线程signal,转移到了同步队列)2.线程被中断也可以退出此循环
    while (!isOnSyncQueue(node)) {
        //线程挂起,挂起后可以由unpark或interrupt结束挂起
        LockSupport.park(this);
        //
        if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)
            break;
    }
    //线程从await状态被signal后,尝试获取锁,和ReentrantLock获取锁一样,该方法返回的是此线程是否被interrupt了
    //如果此线程被interrupt,则执行&&后面的
    if (acquireQueued(node, savedState) && interruptMode != THROW_IE)
        interruptMode = REINTERRUPT;
    if (node.nextWaiter != null) // clean up if cancelled
        unlinkCancelledWaiters();
    if (interruptMode != 0)
        //reportInterrupt
        reportInterruptAfterWait(interruptMode);
}
private Node addConditionWaiter() {
    Node t = lastWaiter;
    // If lastWaiter is cancelled, clean out.
    if (t != null && t.waitStatus != Node.CONDITION) {
        unlinkCancelledWaiters();
        t = lastWaiter;
    }
    //等待队列里的Node都是Condition状态的
    Node node = new Node(Thread.currentThread(), Node.CONDITION);
    if (t == null)
        //是头结点
        firstWaiter = node;
    else
        //加到链表后面
        t.nextWaiter = node;
    lastWaiter = node;
    return node;
}

调用signal方法:

public final void signal() {
    if (!isHeldExclusively())
        throw new IllegalMonitorStateException();
    Node first = firstWaiter;
    if (first != null)
        doSignal(first);
}
private void doSignal(Node first) {
//将node从等待队列转移到同步队列,node的属性也要变更
//唤醒await而挂起的线程,使其能够竞争锁
            do {
                if ( (firstWaiter = first.nextWaiter) == null)
                    lastWaiter = null;
                first.nextWaiter = null;
            } while (!transferForSignal(first) &&
                     (first = firstWaiter) != null);
        }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值