ReentrantLock源码分析--jdk1.8

JDK1.8

ArrayList源码分析--jdk1.8
LinkedList源码分析--jdk1.8
HashMap源码分析--jdk1.8
AQS源码分析--jdk1.8
ReentrantLock源码分析--jdk1.8

ReentrantLock概述

??1. ReentrantLock是独占锁。
??2. ReentrantLock分为公平模式和非公平模式。
??3. ReentrantLock锁可重入(重新插入)

ReentrantLock源码分析

/**
 * @since 1.5
 * @author Doug Lea
 * 独占锁 --默认使用非公平锁模式
 * 可重入
 */
public class ReentrantLock implements Lock, java.io.Serializable {

    private static final long serialVersionUID = 7373984872572414699L;

    private final Sync sync;

    /**
     * Sync内部类,继承AQS,实现独占锁模式,作为基础内部类
     */
    abstract static class Sync extends AbstractQueuedSynchronizer {
        private static final long serialVersionUID = -5179523762034025860L;

        /**
         * 加锁
         */
        abstract void lock();

        /**
         * 判断 reentranLock 状态 是否被锁住(state ?= 0)
         * <p>如果没被锁住尝试 原子性上锁 失败返回false</>
         * <p>如果被锁住 判断是否是当前线程持有锁(重入锁的实现) 如果是 state + 1
         * (信号量  记录该线程持有锁的次数。 该线程每次释放所 信号量 -1。 信号量为零 代表 锁被真正释放)</>
         * <p>else 返回false</p>
         */
        final boolean nonfairTryAcquire(int acquires) {
            final Thread current = Thread.currentThread(); //获取到当前的线程
            int c = getState(); //获取锁的状态
            if (c == 0) { //目前没有人在占有锁 如果锁已被经释放 再次尝试获取锁
                if (compareAndSetState(0, acquires)) { //直接尝试把当前只设置成1,如果成功,把owner设置自己,并且退出
                    setExclusiveOwnerThread(current);
                    return true;
                }
            }
            else if (current == getExclusiveOwnerThread()) { // 如果当前线程为锁的拥有者
                int nextc = c + acquires; //这里就是重入锁的概念,如果还是自己,则进行加1操作,因为释放和获取一定要是对等的
                if (nextc < 0) // overflow
                    throw new Error("Maximum lock count exceeded");
                setState(nextc); // 累加 state 的值  此段代码 实现了重入锁
                return true;
            }
            return false; //当前锁被其他线程占用,退出。
        }

        /**
         * 释放锁,默认releases传1
         */
        protected final boolean tryRelease(int releases) {
            int c = getState() - releases; //获取当前的锁的状态并且减1,因为要释放锁
            if (Thread.currentThread() != getExclusiveOwnerThread()) //如果当前自己不是锁的持有者,只有自己才能释放锁
                throw new IllegalMonitorStateException();
            boolean free = false;
            if (c == 0) { //释放成功
                free = true;
                setExclusiveOwnerThread(null);
            }
            setState(c); //重新设置成状态
            return free;
        }

        /**
         * 如果当前线程独占着锁,返回true
         */
        protected final boolean isHeldExclusively() {
            // While we must in general read state before owner,
            // we don‘t need to do so to check if current thread is owner
            return getExclusiveOwnerThread() == Thread.currentThread();
        }

        /**
         * 条件队列
         */
        final ConditionObject newCondition() {
            return new ConditionObject();
        }

        /**
         * 返回锁的拥有者的线程
         * 当前状态为0返回null,说明在等待中
         * 当前状态不为0返回当前线程
         */
        final Thread getOwner() {
            return getState() == 0 ? null : getExclusiveOwnerThread();
        }

        /**
         * 当前线程占着锁返回 state,否则返回0
         */
        final int getHoldCount() {
            return isHeldExclusively() ? getState() : 0;
        }

        /**
         * state状态不为0标识上锁,为0表示在等待,不上锁
         */
        final boolean isLocked() {
            return getState() != 0;
        }

        /**
         * 反序列化
         */
        private void readObject(java.io.ObjectInputStream s)
            throws java.io.IOException, ClassNotFoundException {
            s.defaultReadObject();
            setState(0); // reset to unlocked state
        }
    }
    /**
     * 构造方法,默认选择非公平锁
     */
    public ReentrantLock() {
        sync = new NonfairSync();
    }

    /**
     * 构造方法,true公平锁,false非公平锁
     */
    public ReentrantLock(boolean fair) {
        sync = fair ? new FairSync() : new NonfairSync();
    }

ReentrantLock继承和实现分析

?? ReentrantLock implements Lock
?? Sync extends AbstractQueuedSynchronizer
?? 1.ReentrantLock实现Lock接口,Lock接口定义了加锁、条件队列、解锁、加锁(中断异常)
?? 2.Sync继承AQS抽象类,实现了独占锁,作为基础内部类

ReentrantLock源码分析

1. FairSync公平锁--内部类

/**
 * 公平锁
 */
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;
            }
        }
        else if (current == getExclusiveOwnerThread()) {
            int nextc = c + acquires;
            if (nextc < 0)
                throw new Error("Maximum lock count exceeded");
            setState(nextc);
            return true;
        }
        return false;
    }
}

2. NonfairSync非公平锁--内部类

/**
 * 非公平锁的同步对象
 */
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); //尝试以独占模式获取锁,如果失败加入node节点到队列中
    }
    protected final boolean tryAcquire(int acquires) {
        return nonfairTryAcquire(acquires);
    }
}
/**
 * 是否有等待线程
 */
public final boolean hasQueuedThreads() {
    return sync.hasQueuedThreads();
}
/**
 * 是否有等待线程
 */
public final boolean hasQueuedThreads() {
    return head != tail;
}

ReentrantLock总结

1)ReentrantLock是可重入的公平/非公平模式的独占锁。
2)ReentrantLock公平锁往往没有非公平锁的效率高,但是,并不是任何场景都是以TPS作为唯一指标,公平锁
能够减少“饥饿”发生的概率,等待越久的请求越能够得到优先满足。

原文地址:https://blog.51cto.com/hackerxian/2429841

时间: 2024-07-30 23:14:21

ReentrantLock源码分析--jdk1.8的相关文章

Java并发编程之ReentrantLock源码分析

ReentrantLock介绍 从JDK1.5之前,我们都是使用synchronized关键字来对代码块加锁,在JDK1.5引入了ReentrantLock锁.synchronized关键字性能比ReentrantLock锁要差,而且ReentrantLock锁功能要比synchronized关键字功能强大. 特点 synchronized关键字和ReentrantLock锁都是重入锁,可重入锁是指当一个线程获取到锁后,此线程还可继续获得这把锁,在此线程释放这把锁前其他线程则不可获得这边锁.相比

AQS源码分析--jdk1.8

JDK1.8 ArrayList源码分析--jdk1.8LinkedList源码分析--jdk1.8HashMap源码分析--jdk1.8AQS源码分析--jdk1.8 AbstractQueuedSynchronizer概述 ??1. AQS是一个基于FIFO队列,可以用于构建锁或者其他相关同步装置的基础框架.??2. AQS提供了双向链表.??3. AQS分为共享模式和独占模式.??4.AQS基于volatile内存可见性和CAS原子性操作实现线程间通信操作. AbstractQueuedS

Java并发编程 ReentrantLock 源码分析

ReentrantLock 一个可重入的互斥锁 Lock,它具有与使用 synchronized 方法和语句所访问的隐式监视器锁相同的一些基本行为和语义,但功能更强大. 这个类主要基于AQS(AbstractOwnableSynchronizer)封装的 公平与非公平锁. 所谓公平锁就是指 在多个线程的争用下,这些锁倾向于将访问权授予等待时间最长的线程,换句话说也就是先被锁定的线程首先获得锁. 非公平锁正好相反,解锁时没有固定顺序. 让我们边分析源代码边学习如何使用该类 先来看一下构造参数,默认

LinkedList源码分析--jdk1.8

JDK1.8 ArrayList源码分析--jdk1.8LinkedList源码分析--jdk1.8 LinkedList概述 ??1.LinkedList是用双向链表实现的集合,基于内部类Node<E>实现的集合.??2.LinkedList支持双向链表访问.克隆.序列化,元素有序且可以重复.??3.LinkedList没有初始化大小,也没有扩容机制,通过头结点.尾节点迭代查找. LinkedList数据结构 ??数据结构是集合的精华所在,数据结构往往也限制了集合的作用和侧重点,了解各种数据

HashMap源码分析--jdk1.8

JDK1.8 ArrayList源码分析--jdk1.8LinkedList源码分析--jdk1.8HashMap源码分析--jdk1.8 HashMap概述 ??1. HashMap是可以动态扩容的数组,基于数组.链表.红黑树实现的集合.??2. HashMap支持键值对取值.克隆.序列化,元素无序,key不可重复value可重复,都可为null.??3. HashMap初始默认长度16,超出扩容2倍,填充因子0.75f.??4.HashMap当链表的长度大于8的且数组大小大于64时,链表结构

ConcurrentHashMap源码分析(JDK1.7和1.8对比)

一.ConcurrentHashMap简介 并发编程大师Doug Lea开发的并发容器之一.ConcurrentHashMap是线程安全且高效的HashMap,在HashMap的基础上增加了线程安全,当然结构方面也有所改变. 为什么要使用ConcurrentHashMap? 1.多线程环境下,HashMap会处于不安全状态.例如put操作可能会引起程序死循环,Cpu占有率达百分百,原因是多线程会导致HashMap的Entry链表形成环形数据结构,如此一来,他的next结点将永不为空,就会产生死循

Vector 源码分析 jdk1.8

Vector简介 Vector 是矢量队列,它是JDK1.0版本添加的类.继承于AbstractList,实现了List, RandomAccess, Cloneable这些接口.Vector 继承了AbstractList,实现了List:所以,它是一个队列,支持相关的添加.删除.修改.遍历等功能.Vector 实现了RandmoAccess接口,即提供了随机访问功能.RandmoAccess是java中用来被List实现,为List提供快速访问功能的.在Vector中,我们即可以通过元素的序

Java并发系列[5]----ReentrantLock源码分析

在Java5.0之前,协调对共享对象的访问可以使用的机制只有synchronized和volatile.我们知道synchronized关键字实现了内置锁,而volatile关键字保证了多线程的内存可见性.在大多数情况下,这些机制都能很好地完成工作,但却无法实现一些更高级的功能,例如,无法中断一个正在等待获取锁的线程,无法实现限定时间的获取锁机制,无法实现非阻塞结构的加锁规则等.而这些更灵活的加锁机制通常都能够提供更好的活跃性或性能.因此,在Java5.0中增加了一种新的机制:Reentrant

ArrayList源码分析--jdk1.8

ArrayList概述   1. ArrayList是可以动态扩容和动态删除冗余容量的索引序列,基于数组实现的集合.  2. ArrayList支持随机访问.克隆.序列化,元素有序且可以重复.  3. ArrayList初始默认长度10,使用Object[]存储各种数据类型. ArrayList数据结构   数据结构是集合的精华所在,数据结构往往也限制了集合的作用和侧重点,了解各种数据结构是我们分析源码的必经之路.  ArrayList的数据结构如下: ArrayList源码分析 /* * 用数