ReentrantLock基本概念

​ ReentrantLock是一个可重入锁,顾名思义,就是支持重进入的锁,它表示该锁能够支持一个线程对资源的重复加锁,并且在获取锁时支持选择公平模式或者非公平模式。与Synchronized不同的是,它使用起来更加灵活,Synchronized加锁释放锁都是隐式的,这种方式简化了锁的管理,但是扩展性不如显示的锁获取和释放的可操作性。

可重入

所谓可重入指的是当一个持有锁的线程再次获取锁时不会被自己阻塞,执行线程在获取锁之后仍然能连续多次地获取到该锁。

公平锁与非公平锁

公平与非公平是针对锁的获取顺序而言的,如果一个锁是公平的,那么锁的获取顺序就需要符合请求的时间顺序,也就是先请求的线程先获得锁。

ReentrantLock源码解析

ReentrantLock实现了Lock接口,因此,先分析一下Lock接口。

Lock接口提供了以上几个方法定义。

public interface Lock {
// 尝试获取锁,如果当前线程获取不到锁,则会进入休眠状态,直到获取到锁为止
void lock(); // 可中断地获取锁,该方法会响应中断,在锁的获取中可以中断当前线程,在获取锁的过程中可以中断当前线程
void lockInterruptibly() throws InterruptedException;
// 尝试非阻塞的获取锁,调用该方法后立刻返回,如果能够成功获取到锁则返回true,否则返回false
boolean tryLock();
/**
在超时时间内获取锁,一下3中情况会返回:
1、当前线程在超时时间内获得了锁
2、当前线程在超时时间内被中断
3、超时时间结束,返回false
*/
boolean tryLock(long time, TimeUnit unit) throws InterruptedException;
// 释放锁
void unlock();
Condition newCondition(); }

ReeterentLock源码

非公平模式
 // 非公平获取锁
final boolean nonfairTryAcquire(int acquires) {
final Thread current = Thread.currentThread();
// 当前线程持有锁的数量
int c = getState();
// 尝试获取锁, 获取成功则返回true
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;
}
释放锁
       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;
setExclusiveOwnerThread(null);
}
setState(c);
return free;
}
公平模式
        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;
}

并发编程原理学习-reentrantlock源码分析的更多相关文章

  1. Java并发编程笔记之ReentrantLock源码分析

    ReentrantLock是可重入的独占锁,同时只能有一个线程可以获取该锁,其他获取该锁的线程会被阻塞后放入该锁的AQS阻塞队列里面. 首先我们先看一下ReentrantLock的类图结构,如下图所示 ...

  2. 多线程高并发编程(8) -- Fork/Join源码分析

    一.概念 Fork/Join就是将一个大任务分解(fork)成许多个独立的小任务,然后多线程并行去处理这些小任务,每个小任务处理完得到结果再进行合并(join)得到最终的结果. 流程:任务继承Recu ...

  3. Java并发编程笔记之ArrayBlockingQueue源码分析

    JDK 中基于数组的阻塞队列 ArrayBlockingQueue 原理剖析,ArrayBlockingQueue 内部如何基于一把独占锁以及对应的两个条件变量实现出入队操作的线程安全? 首先我们先大 ...

  4. Java并发编程中线程池源码分析及使用

    当Java处理高并发的时候,线程数量特别的多的时候,而且每个线程都是执行很短的时间就结束了,频繁创建线程和销毁线程需要占用很多系统的资源和时间,会降低系统的工作效率. 参考http://www.cnb ...

  5. Java并发编程笔记之CyclicBarrier源码分析

    JUC 中 回环屏障 CyclicBarrier 的使用与分析,它也可以实现像 CountDownLatch 一样让一组线程全部到达一个状态后再全部同时执行,但是 CyclicBarrier 可以被复 ...

  6. Java并发编程笔记之CopyOnWriteArrayList源码分析

    并发包中并发List只有CopyOnWriteArrayList这一个,CopyOnWriteArrayList是一个线程安全的ArrayList,对其进行修改操作和元素迭代操作都是在底层创建一个拷贝 ...

  7. Java并发编程笔记之ThreadLocal源码分析

    多线程的线程安全问题是微妙而且出乎意料的,因为在没有进行适当同步的情况下多线程中各个操作的顺序是不可预期的,多线程访问同一个共享变量特别容易出现并发问题,特别是多个线程需要对一个共享变量进行写入时候, ...

  8. Java并发编程笔记之Timer源码分析

    timer在JDK里面,是很早的一个API了.具有延时的,并具有周期性的任务,在newScheduledThreadPool出来之前我们一般会用Timer和TimerTask来做,但是Timer存在一 ...

  9. Java并发编程笔记之PriorityBlockingQueue源码分析

    JDK 中无界优先级队列PriorityBlockingQueue 内部使用堆算法保证每次出队都是优先级最高的元素,元素入队时候是如何建堆的,元素出队后如何调整堆的平衡的? PriorityBlock ...

随机推荐

  1. JavaScript 单线程之异步编程

    Js 单线程之异步编程 先了解一个概念,为什么 JavaScript 采用单线程模式工作,最初设计这门语言的初衷是为了让它运行在浏览器上面.它的目的是为了实现页面的动态交互,而交互的核心是进行 Dom ...

  2. Java高并发-无锁

    一.无锁类的原理 1.1 CAS CAS算法的过程是这样:它包含3个参数CAS(V,E,N).V表示要更新的变量,E表示预期值,N表示新值.仅当V值等于E值时,才会将V的值设为N,如果V值和E值不同, ...

  3. linux篇-linux下源码安装nginx

    LNMP模式 后续继续更新,先搭建nginx 安装环境gcc gcc-c++ 2 下载源码包解压 配置第一个报错 安装openssl openssl-devel yum -y install open ...

  4. 好客租房41-react组件基础综合案例-渲染列表数据

    1渲染列表 在state定义数据 进行数据渲染 //导入react import React from 'react' import ReactDOM from 'react-dom' //导入组件 ...

  5. 构建第一个模型:KNN算法(Iris_dataset)

    利用鸢尾花数据集完成一个简单的机器学习应用~万丈高楼平地起,虽然很基础,但是还是跟着书敲了一遍代码. 一.模型构建流程 1.获取数据 本次实验的Iris数据集来自skicit-learn的datase ...

  6. Tmux终端复用神器使用心得

    tmux在连接远程服务器做实验时很有帮助,可以为每一个项目设置一个Session,在Session中设置不同的Window同时跑多个实验,Window本身还可以分割为多个Pane,在一个视野内利用多个 ...

  7. 可靠的分布式KV存储产品-ETCD-初见

    目录 Paxos Raft(Understandable Distributed Consensus) 名词介绍 Leader Election Log Replication 请求完整流程 etcd ...

  8. Crontab在服务端进行设置定时执行任务

    Crontab简crontab是一个可以根据时间.日期.月份.星期的组合调度对重复任务的执行的守护进程.也可以讲Linux crontab是用来定期执行程序的命令. 当安装完成操作系统之后,默认便会启 ...

  9. 如何写好测试用例以及go单元测试工具testify简单介绍

    背景 ​ 最近在工作和业余开源贡献中,和单元测试接触的比较频繁.但是在这两个场景之下写出来的单元测试貌似不太一样,即便是同一个代码场景,今天写出来的单元测试和昨天写的也不是很一样,我感受到了对于单元测 ...

  10. Spring框架系列(7) - Spring IOC实现原理详解之IOC初始化流程

    上文,我们看了IOC设计要点和设计结构:紧接着这篇,我们可以看下源码的实现了:Spring如何实现将资源配置(以xml配置为例)通过加载,解析,生成BeanDefination并注册到IoC容器中的. ...