腾讯面试题 你了解ReentrantLock吗?

ReetrantLock是一个可重入的独占锁,主要有两个特性,一个是支持公平锁和非公平锁,一个是可重入。

ReetrantLock实现依赖于AQS(AbstractQueuedSynchronizer)(不懂得话可以看我上篇博客)。

ReetrantLock主要依靠AQS维护一个阻塞队列,多个线程对加锁时,失败则会进入阻塞队列。等待唤醒,重新尝试加锁。下图是其类图

支持公平锁和非公平锁

  • 公平锁:多个线程申请获取同一资源时,必须按照申请顺序,依次获取资源。

  • 非公平锁:资源释放时,任何线程都有机会获得资源,而不管其申请顺序。

    具体原理分析

    在new ReetrantLock对象的时候,可以指定其支持公平锁还是非公平锁

    public ReentrantLock() {sync = new NonfairSync();
    }public ReentrantLock(boolean fair) {sync = fair ? new FairSync() : new NonfairSync();
    }
    
  • 公平锁原理

    FairSync继承Sync,而Sync继承AbstractQueuedSynchronizer。ReentrantLock调用lock方法,最终会调用sync的tryAcquire函数,获取资源。FairSync的tryAcquire函数,**当前线程只有在队列为空或者时队首节点的时候,才能获取资源,否则会被加入到阻塞队列中。**下面的hasQueuedPredecessors函数用于判断队列是否为空,或者当前元素是否为队首元素。

    static final class FairSync extends Sync {private static final long serialVersionUID = -3000897897090466540L;final void lock() {acquire(1);}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;}
    }
    

    hasQueuedPredecessors函数,如果h==t(队列为空),或者h!=t && s.thread == Thread.currentThread()(队首节点),则返回false,否则返回true

    public final boolean hasQueuedPredecessors() {Node t = tail; // Read fields in reverse initialization orderNode h = head;Node s;return h != t &&((s = h.next) == null || s.thread != Thread.currentThread());
    }
    
  • 非公平锁原理

    NoFairSync同样继承Sync,ReentrantLock调用lock方法,最终会调用sync的tryAcquire函数,获取资源。而NoFairSync的tryAcquire函数,会调用父类Sync的方法nofairTryAcquire函数。通过对比可以发现,如果资源释放时,新的线程会尝试CAS操作获取资源,而不管阻塞队列中时候有先于其申请的线程。

    static final class NonfairSync extends Sync {private static final long serialVersionUID = 7316153563782823691L;final void lock() {if (compareAndSetState(0, 1))setExclusiveOwnerThread(Thread.currentThread());elseacquire(1);}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;}}else if (current == getExclusiveOwnerThread()) {int nextc = c + acquires;if (nextc < 0) // overflowthrow new Error("Maximum lock count exceeded");setState(nextc);return true;}return false;
    }
    

可重入性

可重入性:获取独占资源的线程,可以重复得获取该独占资源,不需要重复请求。

  • 请求独占资源时,可重入性的体现

    ReentrantLock在申请资源的时候,都会判断当前持有独占资源的线程是不是当前线程,如果是的话,只是简单得将state值加1.记录当前线程的重入次数。

     else if (current == getExclusiveOwnerThread()) {int nextc = c + acquires;if (nextc < 0)throw new Error("Maximum lock count exceeded");setState(nextc);return true;}
    
  • 释放资源时,可重入性的体现

    ReentrantLock在释放资源的时候,都会调用tryRelease,只有state值为0的时候,才会释放资源。换句话说就是,重入多少次,就必须释放多少次

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

腾讯面试题 你了解ReentrantLock吗?相关推荐

  1. android获取指针空间大小_腾讯笔试题:浅谈计算机中cpu位数和指针

    来一个腾讯笔试题 在刷题的时候看到了腾讯笔试题的这个问题 long a = (long)(((int *) 0) + 4);printf("%ld ",a); 请问输出 a 的值是 ...

  2. 腾讯面试题:char 和 varchar的最大长度是多少,以及他们之间的区别(看完你就能和面试官笑谈人生了)

    title: 腾讯面试题:char 和 varchar的最大长度是多少,以及他们之间的区别(看完你就能和面试官笑谈人生了) tags: 面试常见题 腾讯面试题:char 和 varchar的最大长度是 ...

  3. 腾讯面试题:创建索引时,你会怎么考虑呢?(看完你就能和面试官谈人生了)

    title: 腾讯面试题:创建索引时,你会怎么考虑呢?(看完你就能和面试官谈人生了) tags: 面试常见题 腾讯面试题:创建索引时,你会怎么考虑呢?(看完你就能和面试官谈人生了) 腾讯面试题:创建索 ...

  4. 腾讯面试题:给40亿个不重复的unsigned int的整数,没排过序的,然后再给一个数,如何快速判断这个数是否在那40亿个数当中?

    1.腾讯面试题:给40亿个不重复的unsigned int的整数,没排过序的,然后再给一个数,如何快速判断这个数是否在那40亿个数当中? 思想:用数组来存这40亿个数,而且只能用bit来表示.why? ...

  5. 【转】IT名企面试:腾讯笔试题(2)

    摘要:想要进入腾讯公司,面试笔试题是一定要有所准备的.那么这里我们总结了一些腾讯笔试题,例如:const的含义及实现机制等问题. 腾讯是国内数一数二的IT企业了.那么每年想要进入腾讯公司的应聘者也是络 ...

  6. 线性表11|单链表小结:腾讯面试题 - 数据结构和算法16

    线性表11|单链表小结:腾讯面试题 让编程改变世界 Change the world by program 静态链表的删除操作 我们的故事还没结束,小C看到小A和2B这样非法的勾当,内心觉得很不爽,一 ...

  7. 程序员求助:腾讯面试题,64匹马8个跑道,多少轮选出最快的四匹

    昨天,有网友私信我,说去阿里面试,彻底的被打击到了.问了为什么网上大量使用ThreadLocal的源码都会加上private static?他被难住了,因为他从来都没有考虑过这个问题.无独有偶,今天笔 ...

  8. java 2017腾讯面试题_腾讯2017刁难面试题,是不是大神就看你会做几题

    原标题:腾讯2017刁难面试题,是不是大神就看你会做几题 一.今日头条2017笔试题(决策问题) 现在有两堆石子,小今与小条玩游戏,2个人都足够聪明,两个人规定:每次每人只能从其中一堆中取走1个或2个 ...

  9. python编辑距离正则匹配_详解一道腾讯面试题:编辑距离

    原标题:详解一道腾讯面试题:编辑距离 来自公众号:labuladong 预计阅读时间:8 分钟 前几天在网上看到一份鹅场的面试题,算法部分大半是动态规划,最后一题就是写一个计算编辑距离的函数,今天就专 ...

最新文章

  1. PoweMock集成Spring-test 测试静态方法 禁用字节码验证 -noverify -XX:-UseSplitVerifier
  2. HTTP对外接口,如何增加签名机制
  3. Spring :Spring Aop 创建代理
  4. 使用gRPC的.NET Core 3.0双向消息流
  5. Java基础学习总结(65)——Java中的String,StringBuilder和StringBuffer比较
  6. Java 实现HTML 页面转成image 图片
  7. oracle 拉链表 计算和,Oracle拉链表和流水表如何按照时间匹配求新的计算项
  8. ubuntu 12.04 server + OPENACS(TR069)安装配置日记
  9. 对于“增霸卡“的介绍跟使用
  10. Android中的像素密度,屏幕密度,屏幕大小,分辨率,ldpi,mdpi,xhdpi,xxhdpi
  11. 安卓电视/平板玩街机游戏
  12. STM32F407 ETR 计数程序
  13. java计算机毕业设计民航售票管理系统源代码+数据库+系统+lw文档
  14. Word文档怎么翻译?翻译word文档简单步骤讲解
  15. 华为linux系统能用Cad么,华为平板能装cad画图吗 华为平板可以用cad软件吗?
  16. 斐波那契序列递归方法_斐波那契和卢卡斯序列
  17. 解决字符串存在\u6d4b\u8bd5\u5206\u7c7等中文汉字(乱码)(unicode码)
  18. 2022超nice的跨年烟花代码
  19. Yii2如何使用Yii:t()
  20. 对迅雷下载进行投毒的简单尝试

热门文章

  1. HTML中怎么设置超链接字体颜色和点击后的字体颜色
  2. Oracle Spacial(空间数据库)GEOMETRY示例
  3. 在一个静态方法内调用一个非静态成员为什么是非法的
  4. Hive启动 beeline 客户端失败问题解决
  5. 【凯子哥带你做高仿】“煎蛋”Android版的高仿及优化(三)——使用GreenDao实现本地Sqlite缓存
  6. Spring常见错误 - Bean构造注入报空指针异常
  7. 中职计算机网络技术专业教学标准,中等职业学校计算机网络技术专业教学标准.doc...
  8. 吴志祥php动态网页设计_PHP动态网页制作—毕业设计论文.doc
  9. Kaggle Days 来中国了,有人一起组队吗
  10. 从独步全球到缺乏创新,苹果正迷失在5G全面屏时代?