ReentrantLock笔记

来自https://www.bilibili.com/video/BV1ta4y1H73X?from=search&seid=4946324253512830264

 ReehtrahtLock是可重入的意思

表示一个线程如果持有锁A,那么在调用该线程子程序的时候,可以再次重入这个锁(state + 1),不过锁的释放也需要多释放一次

非公平获取锁

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; //是则重入,给state加上acquires(一般为1)
                if (nextc < 0) // overflow
                    throw new Error("Maximum lock count exceeded");
                setState(nextc); // 原子操作
                return true;
            }
            return false;
        }

 对应的示意图如下:

 

释放锁


        protected final boolean tryRelease(int releases) {
            int c = getState() - releases;
            if (Thread.currentThread() != getExclusiveOwnerThread())
                throw new IllegalMonitorStateException();
            boolean free = false;
            if (c == 0) { // 所有锁已经被释放,才会返回true
                free = true;
                setExclusiveOwnerThread(null);
            }
            setState(c);
            return free;//如果还有其他子程序在占有锁,仍然返回false
        }

非公平锁实现的方法

static final class NonfairSync extends Sync {
        private static final long serialVersionUID = 7316153563782823691L;

        /**
         * Performs lock.  Try immediate barge, backing up to normal
         * acquire on failure.
         */
        final void lock() {
            if (compareAndSetState(0, 1))
                setExclusiveOwnerThread(Thread.currentThread());
            else
                acquire(1);
        }

        protected final boolean tryAcquire(int acquires) {
            return nonfairTryAcquire(acquires);
        }
    }

公平锁的实现方法

static final class FairSync extends Sync {
        private static final long serialVersionUID = -3000897897090466540L;

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

        /**
         * Fair version of tryAcquire.  Don't grant access unless
         * recursive call or no waiters or is first.
         */
        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;
                }
            }
            /**下面这个就是重入锁的原理,如果锁属于当前线程,那么可以继续累加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;
        }
    }

Reentrantlock一部分是在jdk级别解决锁问题的,还有一部分会使用os的系统调用,比如park,系统调用是很耗资源的,所以我的理解 轻量级锁和重量级锁的区别,就是轻量级锁是基于jdk的,而重量级锁,是会涉及到系统调用的

并发不见得是竞争的,线程排队示意图如下:

1.6之前reentrantlock性能优于sychronized,但是1.6之后两者性能没有啥区别,不过reentrantlock的API比较丰富多样,比如condition lock条件锁

lock AQS {

自旋

park-unpark

CAS        

}

自旋和cas不是一回事儿,只是再cas的时候可以利用自旋机制来不断重试

自旋是一种锁优化机制,所以锁优化中会有『自旋锁』的概念(线程空转重试获取锁),自旋不一定是用在cas场景,其他锁场景也是能用的(比如互斥锁)

不同线程-- 如果没有共享资源的冲突,其实不会导致AQS队列入队操作--jdk级别解决同步问题

Node类大体设计如下,包含 prev,next,以及当前线程Thread

public class Node {
    Node prev;
    Node next;
    Thread thread;
}

队列的队头的Node里面,Thread的值永远都为空,结构大致如下(Thread左边到Thread右边少了一个next到prev的箭头)

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值