J.U.C之ReentrantLock 可重入锁
* A reentrant mutual exclusion {@link Lock} with the same basic
* behavior and semantics as the implicit monitor lock accessed using
* {@code synchronized} methods and statements, but with extended
* capabilities.
一个可重入的互斥锁,它与使用synchronized的方法和语句来进行隐式锁访问的方式具有相同的基本行为和语义,但是同时具有一些扩展功能。
* <p>The constructor for this class accepts an optional
* <em>fairness</em> parameter. When set {@code true}, under
* contention, locks favor granting access to the longest-waiting
* thread. Otherwise this lock does not guarantee any particular
* access order. Programs using fair locks accessed by many threads
* may display lower overall throughput (i.e., are slower; often much
* slower) than those using the default setting, but have smaller
* variances in times to obtain locks and guarantee lack of
* starvation.
ReentrantLock构造方法接收一个可选的公平参数。当设置为true时,它是公平锁,这时锁会将访问权授予等待时间最长的线程。否则该锁将无法保证线程获取锁的访问顺序。公平锁与非公平锁相比,使用公平锁的程序会有较低的吞吐量,但使用公平锁能有效减少线程饥饿的发生。
使用建议:一般推荐的使用方式就是 lock()后紧跟try块,例如:
class X {
private final ReentrantLock lock = new ReentrantLock();
// ...
public void m() {
lock.lock(); // block until condition holds
try {
// ... method body
} finally {
lock.unlock()
}
}
}}
一、源码解析
private final Sync sync;
/**
* Base of synchronization control for this lock. Subclassed
* into fair and nonfair versions below. Uses AQS state to
* represent the number of holds on the lock.
*/
abstract static class Sync extends AbstractQueuedSynchronizer
/**
* Sync object for non-fair locks
*/
static final class NonfairSync extends Sync
/**
* Sync object for fair locks
*/
static final class FairSync extends Sync
以上为ReentrantLock提供的3个静态内部类,其中Sync类继承自AbstractQueuedSynchronizer(抽象队列同步器),而NonfairSync和FairSync为Sync类的两个实现,分别应用于非公平锁和公平锁的场景,而公平锁和非公平锁在释放锁的情况都是一样的,只是在获取锁时,公平锁会让等待最久的线程优先获取到锁,而非公平锁在获取锁时各线程机会均等,这样也就导致会出现饥饿现象产生.
static final class FairSync extends Sync
final void lock() {acquire(1);}
static final class NonfairSync extends Sync
{
final void lock() {
if (compareAndSetState(0, 1))
setExclusiveOwnerThread(Thread.currentThread());
else
acquire(1);
}
}
以上为公平锁和非公平锁调用lock()的源码,其中的compareAndSetState,setExclusiveOwnerThread和acquire 均来自AQS中,有次可以看出非公平锁在lock时就会去尝试1次去获取锁,获取到了就返回,如果获取不到,则跟公平锁一样,调用acquire(arg)再次尝试获取锁,说白了,非公平锁比公平锁多1次抢占锁的动作。而在抢占动作中,非公平锁是直接尝试抢占,而公平锁会先判断是否位于头结点来决定是否抢占。
非公平锁获取锁源码
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) // overflow
throw new Error("Maximum lock count exceeded");
setState(nextc);
return true;
}
return false;
}
公平锁获取锁源码
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;
}
二、使用场景
场景1 防止重复执行
ReentrantLock lock = new ReentrantLock();
if(lock.tryLock()){//如果已经被lock,则直接放回false,不会等待,达到忽略的效果
try
{
}finally {
lock.unlock();
}
}
场景2 串行执行(同步执行,类似synchronized)
try
{
lock.lock();
}finally {
lock.unlock();
}
场景3 超时等待
try{
if(lock.tryLock(5, TimeUnit.SECONDS)){
try
{
}finally {
lock.unlock();
}
}
}catch (InterruptedException ex){
ex.printStackTrace();
}
场景4 响应中断
try {
lock.lockInterruptibly();
} catch (InterruptedException ex) {
ex.printStackTrace();
} finally {
lock.unlock();
}
J.U.C之ReentrantLock 可重入锁的更多相关文章
- ReenTrantLock可重入锁(和synchronized的区别)总结
ReenTrantLock可重入锁(和synchronized的区别)总结 可重入性: 从名字上理解,ReenTrantLock的字面意思就是再进入的锁,其实synchronized关键字所使用的锁也 ...
- ReentrantLock可重入锁的理解和源码简单分析
import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.ReentrantLock; /** * @author ...
- ReenTrantLock可重入锁和synchronized的区别
ReenTrantLock可重入锁和synchronized的区别 可重入性: 从名字上理解,ReenTrantLock的字面意思就是再进入的锁,其实synchronized关键字所使用的锁也是可重入 ...
- JUC 一 ReentrantLock 可重入锁
java.util.concurrent.locks ReentrantLock即可重入锁,实现了Lock和Serializable接口 ReentrantLock和synchronized都是可重入 ...
- java ReentrantLock可重入锁功能
1.可重入锁是可以中断的,如果发生了死锁,可以中断程序 //如下程序出现死锁,不去kill jvm无法解决死锁 public class Uninterruptible { public static ...
- ReentrantLock——可重入锁的实现原理
一. 概述 本文首先介绍Lock接口.ReentrantLock的类层次结构以及锁功能模板类AbstractQueuedSynchronizer的简单原理,然后通过分析ReentrantLock的lo ...
- 40 多线程(十二)——ReentrantLock 可重入锁
我们使用的synchronized加的锁是可以延续使用的,如下: public void test() { //第一次获得锁 synchronized(this) { while(true) { // ...
- ReentrantLock可重入锁、公平锁非公平锁区别与实现原理
ReentrantLock是lock接口的一个实现类,里面实现了可重入锁和公平锁非公平锁 ReentrantLock公平锁和不公平锁实现原理 公平锁会获取锁时会判断阻塞队列里是否有线程再等待,若有获取 ...
- ReentrantLock可重入锁——源码详解
开始这篇博客之前,博主默认大家都是看过AQS源码的~什么居然没看过猛戳下方 全网最详细的AbstractQueuedSynchronizer(AQS)源码剖析(一)AQS基础 全网最详细的Abstra ...
随机推荐
- python 09 数据包 异常处理
pickle模块操作文件 pickle.dump(obj, file[, protocol]) 序列化对象,并将结果数据流写入到文件对象中.参数protocol是序列化模式,默认值为0,表示以文本的形 ...
- Nginx学习简记_part1
内容概览 nginx简介 (1)介绍nginx的应用场景和具体可以做什么事情 (2)介绍什么是反向代理 (3)介绍什么是负载均衡 (4)介绍什么是动静分离 nginx安装 (1)介绍nginx在lin ...
- .Net Core3.1 + EF Core + LayUI 封装的MVC版后台管理系统
项目名称:学生信息管理系统1.0 后台框架:.Net Core 3.1 + EF Core yrjw.ORM.Chimp 前端框架:ASP.NET Core MVC + LayUI + Bo ...
- 5.SSH 免密码登陆
SSH 免密码登陆 serverA 机器上 userA 用户,想要免密钥登陆到serverB机器上 1.集群中的所有机器 安装ssh 服务端sudo apt-get updatesudo apt-ge ...
- JDBC理论知识
JDBC理论知识 JDBC基础 JDBC(Java Database Connectivity)是一个独立于特定数据库管理系统.通用的SQL数据库存取和操作的公共接口(一组API), 定义了用来访问数 ...
- 并发编程(叁):synchronize
synchronize synchronized是Java中的关键字,是一种常用的线程同步锁. 用法 注意:在理解synchronized时,要知道一个核心点,synchronized锁定的不是代码, ...
- 记录一次CDH集群邮件报警功能的设置
1.通用的配置CDH邮件报警设置 进入cloudera manager service页面,选择配置 左侧菜单Alert Publisher 勾选[启用电子邮件警报] 邮件服务协议smtp,如果使用s ...
- Java开发环境搭建的准备工作
Java开发环境搭建的准备工作 网络配置(修改hosts) 什么时候需要 比如我们在安装homeBrew的时候会遇到 curl: (7) Failed to connect to raw.github ...
- RabbitMQ配置文件(rabbitmq.conf)
rabbitmq.conf配置文件示例: #====================================== #RabbitMQ经纪人部分 #======================= ...
- java返回树形结构的正确姿势
业务场景 通常我们前端需要一个树形的导航菜单或者分类菜单,如后台权限管理中的权限树,亦或者下面例子中商城系统的商品分类多级菜单(一般为三级菜单) 数据库设计 数据库设计,采用parentId来指向自己 ...