JUC-ReentrantLock

1. 作用

基于AQS,在并发编程中实现公平锁、非公平锁对共享资源进行同步,同时,和synchorized一样支持重入,除此之外,调度上更加灵活

2. ReentrantLock implements Lock

ReentrantLock 实现Lock接口

2.1 Lock接口

2.1.1 void lock()

加锁,一直等待,直到获取成功 

2.1.2 void lockInterruptibly() throws InterruptedException;

加锁,一直等待,直到获取成功(假如当前线程在等待锁时被中断,则退出等待,抛出中断异常)

2.1.3 boolean tryLock();

尝试获取锁,并立即返回

2.1.4 boolean tryLock(long time, TimeUnit unit) throws InterruptedException;

在一段时间内获取锁(假如当前线程在等待锁时被中断,则退出等待,抛出中断异常)

2.1.5 void unlock();

释放锁

2.1.6 Condition newCondition();

新建一个绑定在当前对象上的condition对象。作用?

3. private final Sync sync

唯一的变量 Sync,一旦被指定,后期无法修改

3.1 Sync

3.1.1 abstract void lock()

抽象方法,需要NonfairSync、FairSync实现(实现是否公平的获取锁)

3.1.2 boolean nonfairTryAcquire(int acquires) 

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

非公平的尝试获取锁

 3.1.3 boolean tryRelease(int releases)

方法含义:锁是否完全被释放。。假如:state=10, tryRelease了1次,state=9,此时返回的是false,而不是本次释放1次并且成功

        protected final boolean tryRelease(int releases) {
            int c = getState() - releases;
            if (Thread.currentThread() != getExclusiveOwnerThread())
                throw new IllegalMonitorStateException();
            boolean free = false;
            if (c == 0) {

                // 只有state=0时,才认为当前线程完全释放了锁
                free = true;
                setExclusiveOwnerThread(null);
            }
            setState(c);
            return free;
        }

3.1.4 ConditionObject newCondition()

返回一个ConditionObject对象

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

3.1.5 Thread getOwner()

获取当前锁的线程

        final Thread getOwner() {
            return getState() == 0 ? null : getExclusiveOwnerThread();
        }

3.1.6 int getHoldCount()

获取当前有多少线程在等待锁

        final int getHoldCount() {
            return isHeldExclusively() ? getState() : 0;
        }

3.1.7 boolean isLocked()

当前是否有锁

        final boolean isLocked() {
            return getState() != 0;
        }

3.2 NonfairSync

3.2.1 void lock()

        final void lock() {
            // 尝试获取锁,如果成功,将当前锁的拥有者设置为 当前线程
            if (compareAndSetState(0, 1))
                setExclusiveOwnerThread(Thread.currentThread());
            else
            // 获取锁失败,进入等待队列
                acquire(1);
        }

3.2.2 boolean tryAcquire(int acquires)

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


        final boolean nonfairTryAcquire(int acquires) {
            final Thread current = Thread.currentThread();
            int c = getState();

            //  锁空闲时的处理
            if (c == 0) {
                if (compareAndSetState(0, acquires)) {
                    setExclusiveOwnerThread(current);
                    return true;
                }
            }
        
     // 可重入性的判断,c表示锁被获取的次数,int最大值+1 后为负数,因此可重入的次数为int最大值
            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;
        }

3.3 FairSync

3.3.1 lock()

公平模式获取锁

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


    public final void acquire(int arg) {
        // 公平模式下的尝试获取锁
        if (!tryAcquire(arg) &&

            // 假如等待队列
            acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
            selfInterrupt();
    }

3.3.2 boolean tryAcquire(int acquires)

尝试获取锁:当前锁空闲加锁的当前线程才会获取锁成功

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

4. 公平模式与非公平模式下的获取锁的区别

4.1 实现方式

state=0时,此时锁是空闲状态

公平模式:判断是否有等待队列,如果没有,才会尝试获取锁,否则tryAcquire失败  hasQueuedPredecessors()

非公平模式:不会管是否有等待队列

4.2 性能区别

当前线程可能存在 在休眠线程unpark醒来之前拿到锁,在这段时间执行完,释放锁。此时休眠的线程醒来后,也能拿到锁。

JUC-ReentrantLock_第1张图片

在休眠线程醒来之前的时间段,已经有一个任务“加锁、执行业务逻辑、释放锁 ”,,因此性能更高

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