ReentrantLock:

  1. 源码层面分析:

    public class ReentrantLock implements Lock, java.io.Serializable {private static final long serialVersionUID = 7373984872572414699L;//实现同步逻辑的同步器,提供了所有锁相关的操作private final Sync sync;//默认构造函数,提供了非公平锁public ReentrantLock() {sync = new NonfairSync();}/*** 根据策略(公平,非公平)来构建重入锁* @param fair true表示采用公平锁,false表示采用非公平锁*/public ReentrantLock(boolean fair) {sync = fair ? new FairSync() : new NonfairSync();}//获取锁,获取成功则返回,否则阻塞获取线程直到获取成功public void lock() {sync.lock();}//获取锁,获取成功则返回,否则阻塞获取线程直到获取成功;并响应中断,也就是说获取线程被Thread.interrupt()中断后,该方法会抛出InterruptedException并返回。public void lockInterruptibly() throws InterruptedException {sync.acquireInterruptibly(1);}/** * 尝试获取锁,不管成功,失败都立即返回,不会阻塞* @return true表示获取成功,false表示失败*/       public boolean tryLock() {return sync.nonfairTryAcquire(1);}/** * 尝试获取锁,获取成功则返回,否则等待timeout时间返回* @param timeout 等待获取锁的超时时间* @param unit 时间单位* @return true表示获取成功,false表示超时时间到达仍然获取失败 */public boolean tryLock(long timeout, TimeUnit unit)throws InterruptedException {return sync.tryAcquireNanos(1, unit.toNanos(timeout));}//释放锁,该方法不会阻塞public void unlock() {sync.release(1);}/** * 获取一个条件对象* @return 条件对象*/   public Condition newCondition() {return sync.newCondition();}
  2. Sync内部类:

    //同步抽象类,基于AQS实现
    abstract static class Sync extends AbstractQueuedSynchronizer {private static final long serialVersionUID = -5179523762034025860L;//具体由子类NoFairSync,FairSync实现abstract void lock();/*** 非公平的方式尝试获取资源* @param acquires 资源个数* @return true表示获取成功,false获取失败*/final boolean nonfairTryAcquire(int acquires) {final Thread current = Thread.currentThread();//获取资源状态,volatile读int c = getState();//0表示初始状态或者锁释放状态,可以直接获取资源if (c == 0) {//CAS判断资源获取是否成功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;}/*** 尝试释放资源* @param releases 资源个数* @return true表示释放成功,false释放失败*/protected final boolean tryRelease(int releases) {int c = getState() - releases;//如果当前线程不为持有资源的线程,则抛出异常if (Thread.currentThread() != getExclusiveOwnerThread())throw new IllegalMonitorStateException();boolean free = false;//如果释放后,资源的个数为0表示释放成功if (c == 0) {free = true;//设置资源的独占线程为null,此时没有线程占用资源setExclusiveOwnerThread(null);}setState(c);return free;}/*** 判断当前线程是否持有资源* @return true表示是,false表示否*/protected final boolean isHeldExclusively() {return getExclusiveOwnerThread() == Thread.currentThread();}/*** 获取条件对象* @return 新的条件对象*/final ConditionObject newCondition() {return new ConditionObject();}/*** 获取持有资源的线程* @return 持有资源的线程*/final Thread getOwner() {return getState() == 0 ? null : getExclusiveOwnerThread();}/*** 获取持有资源的个数* @return 持有资源的个数*/final int getHoldCount() {return isHeldExclusively() ? getState() : 0;}/*** 获取资源是否被线程占用* @return true表示是,false否*/final boolean isLocked() {return getState() != 0;}
    }
    

    ReentrantLock内部基于Sync提供了非公平锁和公平锁的实现。

  3. 非公平锁

    //非公平锁继承自Syncstatic final class NonfairSync extends Sync {private static final long serialVersionUID = 7316153563782823691L;/*** 非公平锁提供的锁定方法*/final void lock() {//先尝试CAS获取操作,获取成功则设置当前线程为资源持有线程并返回if (compareAndSetState(0, 1))setExclusiveOwnerThread(Thread.currentThread());else//获取失败则进入AQS的acquire逻辑,排队获取资源acquire(1);}   /*** 非公平的方法尝试获取资源,AQS对外提供的需要实现方法* @param acquires资源个数* @return true表示是,false否*/protected final boolean tryAcquire(int acquires) {//用Sync类的非公平方式尝试获取资源return nonfairTryAcquire(acquires);}}
    
  4. 公平锁:

    static final class FairSync extends Sync {private static final long serialVersionUID = -3000897897090466540L;/*** 公平锁提供的锁定方法*/final void lock() {//排队获取资源,体现公平性acquire(1);}/*** 公平的方式尝试获取资源* @param acquires资源个数* @return true表示是,false否*/protected final boolean tryAcquire(int acquires) {final Thread current = Thread.currentThread();int c = getState();//0表示当前可以直接获取资源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;}
    }
    
  5. **总结:**非公平主要体现在资源获取时,如果获取线程发现当前资源可以获取成功(其他线程释放了资源)那就直接获取返回,而此时可能有其他线程先于当前线程在排队获取,那么对于这部分线程来说是“不公平”的,没有体现先到先得的原则。反之,就是公平锁,先排队的线程先获取锁,不存在插队的情况,体现了公平性,所以叫公平锁。

  6. ReentrantLock默认使用非公平方式提供锁的获取和释放,可以看到相比公平模式,非公平模式获取锁的效率更高,因为在非公平模式下如果能够获取锁成功则线程不需要再排队,而在公平模式下,所有线程都必须排队获取锁,所以从当前获取锁的线程的角度非公平模式效率更高。还有一个地方需要说明的是:ReentrantLock是可重入锁,也就是说同一个线程获取锁后可再次重复获取锁无需阻塞。

  7. 典型应用场景:

    class X {private final ReentrantLock lock = new ReentrantLock();private Condition condition = lock.newCondition(); public void m() {lock.lock();  // 获取锁try {try {//必须先获取锁才能执行条件等待,其他线程需要执行condition.signal()方法,来唤醒等待线程condition.await();} catch (InterruptedException e) {e.printStackTrace();}// 执行具体业务方法} finally {lock.unlock() //释放锁,必须在finally块中,防止发生异常时未执行释放锁操作,导致其他线程无法获取锁}}}}
    

Java并发编程之ReentrantLock重入锁相关推荐

  1. Java 并发编程之可重入锁 ReentrantLock

    Java 提供了另外一个可重入锁,ReentrantLock,位于 java.util.concurrent.locks 包下,可以替代 synchronized,并且提供了比 synchronize ...

  2. Java并发编程之CyclicBarrier详解

    简介 栅栏类似于闭锁,它能阻塞一组线程直到某个事件的发生.栅栏与闭锁的关键区别在于,所有的线程必须同时到达栅栏位置,才能继续执行.闭锁用于等待事件,而栅栏用于等待其他线程. CyclicBarrier ...

  3. 【java】动态高并发时为什么推荐重入锁而不是Synchronized?

    1.概述 转载:http://www.dreamwu.com/post-1758.html 这个图画的不错,有助于加深理解. [Java]Synchronized 有几种用法 [java] 从hots ...

  4. java并发编程之4——Java锁分解锁分段技术

    转载自 java并发编程之4--Java锁分解锁分段技术 并发编程的所有问题,最后都转换成了,"有状态bean"的状态的同步与互斥修改问题.而最后提出的解决"有状态bea ...

  5. zbb20180929 thread java并发编程之Condition

    java并发编程之Condition 引言 在java中,对于任意一个java对象,它都拥有一组定义在java.lang.Object上监视器方法,包括wait(),wait(long timeout ...

  6. 浅析ReentrantLock重入锁

    在 Java 多线程中, 可以使用 synchronized 关键字来实现多线程之间同步互斥, 但在 JDK 1.5 中新增加了 ReentrantLock 类也能达到同样的效果, 并且在扩展功能上也 ...

  7. Java并发编程之CAS第三篇-CAS的缺点

    Java并发编程之CAS第三篇-CAS的缺点 通过前两篇的文章介绍,我们知道了CAS是什么以及查看源码了解CAS原理.那么在多线程并发环境中,的缺点是什么呢?这篇文章我们就来讨论讨论 本篇是<凯 ...

  8. Java 并发编程之美:并发编程高级篇之一-chat

    借用 Java 并发编程实践中的话:编写正确的程序并不容易,而编写正常的并发程序就更难了.相比于顺序执行的情况,多线程的线程安全问题是微妙而且出乎意料的,因为在没有进行适当同步的情况下多线程中各个操作 ...

  9. Java 并发编程之美:并发编程高级篇之一

    借用 Java 并发编程实践中的话:编写正确的程序并不容易,而编写正常的并发程序就更难了.相比于顺序执行的情况,多线程的线程安全问题是微妙而且出乎意料的,因为在没有进行适当同步的情况下多线程中各个操作 ...

最新文章

  1. 【腾讯bugly干货分享】微信Android热补丁实践演进之路
  2. Kafka单机、集群模式安装详解(一)
  3. 【反爬】某网站雪碧图反爬
  4. 将本地Blog部署到GitHub上,有自己的博客页面!
  5. 谷歌浏览器手势_分享一些日常手势[狗头]
  6. ado jet 反复连接 未指定的错误_为什么驱动器的PE端要和变压器中性点有可靠连接?...
  7. 微信扫码登录实现原理
  8. PostMan 之 Mock 接口测试
  9. 这辈子都没有好好的认认真真的过过一天
  10. 熊猫烧香源码分析_熊猫体育分析入门
  11. 【mediasoup 带宽估计】aimd算法2 : AimdRateControl
  12. jquery stop()方法的讲解使用
  13. mysql历史数据自动归档
  14. http 常用的默认端口号
  15. 四时之气,汇聚英豪胆略
  16. 如何学好iphone游戏开发
  17. CNN卷积神经网络案例程序源代码合集matlab/Python等
  18. 【书签】stacking、blending
  19. 架构师图谱之微服务消息队列
  20. CodeForces 356 C.Compartments(贪心)

热门文章

  1. 用Python告诉你,为什么宇宙的尽头是公务员!
  2. 【数据结构与算法】主宰这个世界的10大算法
  3. 《Cortex-M0权威指南》之Cortex-M0编程入门
  4. android消息机制 Message, Looper,Handler
  5. 男女择偶基本心理类型
  6. 美图影像节发布六款新品 满足用户生活、工作全方位变美需求
  7. 中国电信:1月5G套餐用户数净增826万户
  8. 富士康已看到芯片短缺开始缓解迹象 预计下半年会有改善
  9. 真快!iOS 15.4支持戴口罩解锁了:苹果终于满足iPhone用户需求
  10. 微信3.3.0 for Mac全新发布:新增视频号 可搜索微信号添加朋友