【并发编程】锁-源码分析

1、ReentrantLock

1.1 加锁流程源码

1.1.1 加锁流程概述

【并发编程】锁-源码分析_第1张图片

1.1.2 lock源码分析

1.1.2.1 公平和非公平锁方式

【并发编程】锁-源码分析_第2张图片

// 非公平锁
final void lock() {
    // 上来就先基于CAS的方式,尝试将state从0改为1
    if (compareAndSetState(0, 1))
        // 获取锁资源成功,会将当前线程设置到exclusiveOwnerThread属性,代表是当前线程持有着锁资源
        setExclusiveOwnerThread(Thread.currentThread());
    else
        // 执行acquire,尝试获取锁资源
        acquire(1);
}

// 公平锁
final void lock() {
    //  执行acquire,尝试获取锁资源
    acquire(1);
}
1.1.2.2 acquire方法

public final void acquire(int arg) {
    // tryAcquire:再次查看,当前线程是否可以尝试获取锁资源
    if (!tryAcquire(arg) &&
        // 没有拿到锁资源
        // addWaiter(Node.EXCLUSIVE):将当前线程封装为Node节点,插入到AQS的双向链表的结尾
        // acquireQueued:查看我是否是第一个排队的节点,如果是可以再次尝试获取锁资源,如果长时间拿不到,挂起线程
        // 如果不是第一个排队的额节点,就尝试挂起线程即可
        acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
        // 中断线程的操作
        selfInterrupt();
}
1.1.2.3 tryAcquire方法

【并发编程】锁-源码分析_第3张图片

// 非公平锁实现
final boolean nonfairTryAcquire(int acquires) {
    // 获取当前线程
    final Thread current = Thread.currentThread();
    // 获取了state熟属性
    int c = getState();
    // 判断state当前是否为0,之前持有锁的线程释放了锁资源
    if (c == 0) {
        // 再次抢一波锁资源
        if (compareAndSetState(0, acquires)) {
            setExclusiveOwnerThread(current);
            // 拿锁成功返回true
            return true;
        }
    }
    // 不是0,有线程持有着锁资源,如果是,证明是锁重入操作
    else if (current == getExclusiveOwnerThread()) {
        // 将state + 1
        int nextc = c + acquires;
        if (nextc < 0) // 说明对重入次数+1后,超过了int正数的取值范围
            // 01111111 11111111 11111111 11111111
            // 10000000 00000000 00000000 00000000
            // 说明重入的次数超过界限了。
            throw new Error("Maximum lock count exceeded");
        // 正常的将计算结果,复制给state
        setState(nextc);
        // 锁重入成功
        return true;
    }
    // 返回false
    return false;
}


// 公平锁实现
protected final boolean tryAcquire(int acquires) {
    // 获取当前线程
    final Thread current = Thread.currentThread();
    // ....
    int c = getState();
    if (c == 0) {
        // 查看AQS中是否有排队的Node
        // 没人排队抢一手 。有人排队,如果我是第一个,也抢一手
        if (!hasQueuedPredecessors() &&
            // 抢一手~
    

你可能感兴趣的:(并发编程,java,开发语言)