ReentrantLock概述

ReentrantLock是Lock接口的实现类,可以手动的对某一段进行加锁。ReentrantLock可重入锁,具有可重入性,并且支持可中断锁。其内部对锁的控制有两种实现,一种为公平锁,另一种为非公平锁。ReentrantLock的实现原理为volatile+CAS

ReentrantLock可重入性

ReentrantLock具有可重入性,可重入性是指当一个线程拥有一个方法的锁以后,是否还可以进入该方法,一般这种情况出现在递归中。ReentrantLock的可重入性是基于Thread.currentThread()实现的,是线程粒度的,也就是说当前线程获得一个锁以后,当前线程的所有方法都可以获得这个锁。Reentrant依赖的锁只有两种实现类,NonFairSync和FairSync,但是它们获取锁的方式大同小异。一下是公平锁的获取实现。ReentrantLock.FairSync.tryAcquire

 protected final boolean tryAcquire(int acquires) {
final Thread current = Thread.currentThread();
int c = getState();
//每一次加锁state+1
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;
}
}

ReentrantLock锁的实现分析

ReentrantLock有两种锁的实现,FairSync和NonFairSync,对于这两种锁,他们获取锁的方式都大同小异ReentrantLock$Sync#acquire

    public final void acquire(int arg) {
//通过tryAcquire去尝试获取锁,公平锁和非公平锁有不同的实现
if (!tryAcquire(arg) &&
//如果没有获取到,就将该线程加入等待队列,然后循环尝试获取该锁
acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
//如果尝试获取锁的次数达到一定次数,就会触发中断,中断该线程,并释放锁
selfInterrupt();
}

tryAcquire():尝试获取锁;

addWaiter():将线程加入等待队列

acquireQueued():在多次循环中尝试获取到锁或者将当前线程堵塞

selfInterrupt():如果多次未获取成功,将中断该线程(避免死锁)

公平锁(FairSync)

公平锁内部维护了一个等待获取该锁的线程的队列,会按照队列顺序给每个线程锁。每当抢占锁的时候,就会判断是否有等待队列,如果有等待队列,就从等待队列的头开始分配锁

         protected final boolean tryAcquire(int acquires) {
//取得当前请求锁的线程
final Thread current = Thread.currentThread();
//取得stage,每一次加锁,stage都会+1,如果stage是0,就说明,没有人使用该锁
int c = getState();
if (c == 0) {
//如果没有等待队列,并且CAS通过,就将当前线程就抢到了锁
if (!hasQueuedPredecessors() &&
compareAndSetState(0, acquires)) {
setExclusiveOwnerThread(current);
return true;
}
}
//如果锁没有释放,就判断当前线程是否是该锁的拥有者,如果是,可以直接使用该改,并stage+1
else if (current == getExclusiveOwnerThread()) {
int nextc = c + acquires;
if (nextc < 0)
throw new Error("Maximum lock count exceeded");
setState(nextc);
return true;
}
//如果没有抢到锁,就返回false
return false;
}

非公平锁(NonFairSync)

非公平锁在抢占锁时,会进行随机抢占,后抢占的线程往往抢占到的几率比较大。

 if (c == 0) {
//非公平锁仅仅是使用CAS,并不会去查看队列(也没有队列)
if (compareAndSetState(0, acquires)) {
setExclusiveOwnerThread(current);
return true;
}
}

ReentrantLock的内存可见性

ReentrantLock保证内存可见性,作用和synchronized一样,但是要比synchronized更加灵活,方便,ReentrantLock可以和Condition联合使用

ReentrantLock详解的更多相关文章

  1. Lock的实现之ReentrantLock详解

    摘要 Lock在硬件层面依赖CPU指令,完全由Java代码完成,底层利用LockSupport类和Unsafe类进行操作: 虽然锁有很多实现,但是都依赖AbstractQueuedSynchroniz ...

  2. java之ReentrantLock详解

    前言 如果一个代码块被synchronized修饰了,当一个线程获取了相应的锁,并执行该代码块时,其他线程便只能一直等待,等待获取锁的释放,现在有这么一种情况,这个获取锁的线程由于要等待IO或者其他原 ...

  3. ReentrantLock 详解

    ReentrantLock的功能是实现代码段的并发访问控制,也就是通常意义上所说的锁,java中实现锁有两种方式,一种是本文所提的ReentrantLock,另一种是synchronized.Reen ...

  4. ReentrantLock详解 以及与synchronized的区别

    ReentrantLock lock = new ReentrantLock(); //参数默认false,不公平锁 ReentrantLock lock = new ReentrantLock(tr ...

  5. Java并发之ReentrantLock详解

    一.入题 ReentrantLock是Java并发包中互斥锁,它有公平锁和非公平锁两种实现方式,以lock()为例,其使用方式为: ReentrantLock takeLock = new Reent ...

  6. 图解AQS原理之ReentrantLock详解-非公平锁

    概述 并发编程中,ReentrantLock的使用是比较多的,包括之前讲的LinkedBlockingQueue和ArrayBlockQueue的内部都是使用的ReentrantLock,谈到它又不能 ...

  7. 从ReentrantLock详解AQS原理源码解析

    数据结构 java.util.concurrent.locks.AbstractQueuedSynchronizer类中存在如下数据结构. // 链表结点 static final class Nod ...

  8. 最强Java并发编程详解:知识点梳理,BAT面试题等

    本文原创更多内容可以参考: Java 全栈知识体系.如需转载请说明原处. 知识体系系统性梳理 Java 并发之基础 A. Java进阶 - Java 并发之基础:首先全局的了解并发的知识体系,同时了解 ...

  9. java并发编程 | 锁详解:AQS,Lock,ReentrantLock,ReentrantReadWriteLock

    原文:java并发编程 | 锁详解:AQS,Lock,ReentrantLock,ReentrantReadWriteLock 锁 锁是用来控制多个线程访问共享资源的方式,java中可以使用synch ...

随机推荐

  1. Sharepoint学习笔记—修改SharePoint的Timeouts (Execution Timeout)

    有时在Sharepoin中有些执行任务可能会超过Sharepoint环境默认的Timout限制,这种情况下系统会报"Request Timed out"错误.对此我们可以在两个层次 ...

  2. Linux文件压缩和解压缩命令

    Linux文件压缩和解压缩命令: tar 命令(打包并压缩的话,原文件也会默认存在) -c 建立打包档案 -x 解包 -t 查看包里的类容 -r 向包里追加文件 -v 显示打包过程 -f 文件 比如: ...

  3. May 27th 2017 Week 21st Saturday

    I learned the value of hard work by working hard. 只有真的努力了,才会知道努力的价值. I remember in the movie, The Da ...

  4. ZT 自定义operator new与operator delete的使用(1)

    http://blog.csdn.net/waken_ma/article/details/4004972 先转两篇文章: 拨开自定义operator new与operator delete的迷雾 C ...

  5. git多站点多用户情况下SSH配置

    个人使用github,但是公司使用的是 GitLab .那么在一个电脑上进行处理时,由于先设置了 github 的,导致没办法从 GitLab 上处理 git .其实是由于 ssh 的问题. 下面记录 ...

  6. fast、faster中ap值的计算

    def voc_ap(rec, prec, use_07_metric=False): """ ap = voc_ap(rec, prec, [use_07_metric ...

  7. git bush 代码提交

    # git add . # git commit -m"init project" # git push

  8. 不能安装这个“安装 OS X EI Capitan”应用程序副本不能验证” 的解决办法

    不能安装这个“安装 OS X EI Capitan”应用程序副本不能验证.它在下载过程中可能已遭破坏或篡改. 解决办法:修改系统时间. 1,查看你的dmg文件的创建日期 2,把你的系统日期修改到比这个 ...

  9. html下载文件和上传文件(图片)(java后台(HttpServlet))打开保存路径和选择文件录取+(乱码UTF-8)+包

    下载文件: //通过路径得到一个输入流 String path = "获取需要下载的文件路径"; //path.lastIndexOf(".")+1可以获取文件 ...

  10. data-ng-show指令

    <!DOCTYPE html><html><head><meta http-equiv="Content-Type" content=&q ...