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 ...
随机推荐
- J20航模遥控器开源项目系列教程(二)使用说明 | 遥控器制作完成了,怎么用?
我们的开源宗旨:自由 协调 开放 合作 共享 拥抱开源,丰富国内开源生态,开展多人运动,欢迎加入我们哈~ 和一群志同道合的人,做自己所热爱的事! 项目开源地址:https://github.com/C ...
- 个人项目wc(C语言)
github地址:https://github.com/nilonger/mycangku 一.项目要求 1.wc.exe 是一个常见的工具,它能统计文本文件的字符数.单词数和行数.这个项目要求写一个 ...
- Windows 远程桌面鼠标光标不可见
一.问题描述 通过在云端的主机上部署 frp 服务,实现「使用Windows 远程桌面(RDP)从互联网侧访问内网的主机」.但是,使用 Windows 自带的远程桌面工具 RDP 连接到另一台计算机时 ...
- C++ int与char[]的相互转换
C++ int与char[]的相互转换 一.itoa函数与atio函数①把int类型数字转成char类型,可以使用itoa函数. itoa函数原型: char*itoa(int value,char* ...
- el-table表头v-for循环遇到的问题
这两天在项目中遇到了el-table表头需要动态变化,也就是点击不同的标签显示对应的表格,主要表头都不一样,那么表格也就是动态的,表头也需要循环 一开始以为很简单 <el-table ...
- json对象遍历顺序问题
对json对象遍历我们一般使用for in循环,或者Object.keys + 数组方法.在接触js以来听到过一种说法: for in 遍历顺序是不可靠的 但是在实际开发中for in 循环也是按照其 ...
- AlexNet实现cifar10数据集分类
import tensorflow as tf import os from matplotlib import pyplot as plt import tensorflow.keras.datas ...
- SpringCloud Alibaba Nacos 服务注册
业务服务接入Nacos服务治理中心 启动Nacos访问地址为:http://101.200.201.195:8848/nacos/ 创建bom工程用于管理依赖(下方附加源码地址) 准备工作完成后开始接 ...
- VSCode优雅编码
安装eslint 修改eslint配置 rules: { 'no-console': process.env.NODE_ENV === 'production' ? 'error' : 'off', ...
- 【HttpRunner v3.x】笔记—8.运行testcase的几种方式
在之前的demo过程中,已经运行过testcase了,那这篇就也来汇总一下,运行case相关的知识点. 一.运行testcase的几种场景 1. 运行单个case 通常单个case的话我会在编辑器里用 ...