JAVA并发锁(二) - 重入锁公平性分析

2024-02-22 09:08

本文主要是介绍JAVA并发锁(二) - 重入锁公平性分析,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

ReentrantLock 原理分析

CAS与Unsafe

Unsafe

该类在 sun.misc.Unsafe 中,是一个final类型的类,是不可继承类,同时类中大部分操作都是native方法,调用本地方法来进行硬件操作。几个常见的方法:

// 获取类变量在内存中的偏移地址
public native long staticFieldOffset(Field var1);
// 获取实例变量在内存中的偏移地址
public native long objectFieldOffset(Field var1);
// 获取数组的第一个元素的偏移地址
public native int arrayBaseOffset(Class<?> var1);
// 获取数组中元素的增量地址
public native int arrayIndexScale(Class<?> var1);
// 原子操作比较交换对象的值
public final native boolean compareAndSwapObject(Object var1, long var2, Object var4, Object var5);
// 原子操作比较交换Integer类型的值
public final native boolean compareAndSwapInt(Object var1, long var2, int var4, int var5);
// 原子操作比较交换Long类型的值
public final native boolean compareAndSwapLong(Object var1, long var2, long var4, long var6);

CAS[compare and swap], 比较和交换。

在java中整个并发操作都依赖于CAS,CAS在java.util.concurrent[J.U.C]中地位很高,很多并发操作都由CAS来实现。它是一种无锁算法,在不适用锁的情况下,实现多线程之间变量的共享,乐观锁的实现的一种。

CAS有三个操作数:
1.内存值V
2.需要进行比较的值A,(可理解为在没有其它线程操作时从内存中获取到的值)
3.需要更新的值B

CAS比较交换原则:当且仅当A与V的值相等,才会进行更新操作(将B值写入到内存中),否则会一直循环,进行比较,直到A与V值相等后退出。比较+更新 是一个原则操作。
AtomicInteger 类:

public class AtomicInteger extends Number implements java.io.Serializable {private static final long serialVersionUID = 6214790243416807050L;// setup to use Unsafe.compareAndSwapInt for updatesprivate static final Unsafe unsafe = Unsafe.getUnsafe();// cas中需要比较的值A在内存中的偏移位置private static final long valueOffset;static {try {valueOffset = unsafe.objectFieldOffset(AtomicInteger.class.getDeclaredField("value"));} catch (Exception ex) { throw new Error(ex); }}// cas中需要比较的值A,采用volatile 修饰,表示线程间可见。private volatile int value;...
}

AtomicInteger 类中的 final int addAndGet(int delta) ,更新 Integer值的原子操作:

public final int addAndGet(int delta) {return unsafe.getAndAddInt(this, valueOffset, delta) + delta;
}
public final int getAndAddInt(Object var1, long var2, int var4) {int var5;do {var5 = this.getIntVolatile(var1, var2);} while(!this.compareAndSwapInt(var1, var2, var5, var5 + var4));return var5;
}

e.g.
声明:以下 T1,T2,T3 时刻是指线程之间的上下文切换时刻。

假设有三个线程Thread1,Thread2,Thread3, 开始时AtomicInteger 中的value值为3,也就是A=3, V=3。
T1时刻,三个线程都没有作任何更新操作,只有Thread1作读操作。
T2时刻,Thread2需要作更新操作,需要更新的值B=4。整个原子操作过程,首先会将A值与内存V值进行比较,发现A=V,那么接下来会将B值写入到内存中,即V=4,那么此时期望比较的值A也等于4。
T3时刻,Thread1也需要进行更新操作,但是发现期望值A!=内存值V,那么不会进行更新操作,此时Thread1会循环进行比较,直到A=V时,将值B写入到内存中,或者经过一段时间返回false。
T4时刻,Thread3进行读操作,不做任何处理,直接将内存值V返回即可。

整个操作过程如下图所示:
在这里插入图片描述

CAS 问题

  • ABA问题
    一个线程在更新之前会进行比较,这没有任何问题,但是在比较之前,如果其它线程将内存值从原来的V=3变成V=4,再变成V=3,那么在需要更新操作的线程中,比较A与V值时,发现没有任何变化,即A==V,那么需要更新的线程会误以为没有更新过,会直接将数据B写入到内存中,但是在内存中确实V值进行过更新。

可通过对内存值V进行版本标记的方式解决。

  • 可能造成无限循环,耗时耗内存
    在比较A与V时,如果A与V一直不相等,那么cas会无限循环的去比较,直到A==V时,才会退出cas,进行线程的其它操作。造成长时间的消耗内存。

这篇关于JAVA并发锁(二) - 重入锁公平性分析的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/734771

相关文章

springboot集成easypoi导出word换行处理过程

《springboot集成easypoi导出word换行处理过程》SpringBoot集成Easypoi导出Word时,换行符n失效显示为空格,解决方法包括生成段落或替换模板中n为回车,同时需确... 目录项目场景问题描述解决方案第一种:生成段落的方式第二种:替换模板的情况,换行符替换成回车总结项目场景s

SpringBoot集成redisson实现延时队列教程

《SpringBoot集成redisson实现延时队列教程》文章介绍了使用Redisson实现延迟队列的完整步骤,包括依赖导入、Redis配置、工具类封装、业务枚举定义、执行器实现、Bean创建、消费... 目录1、先给项目导入Redisson依赖2、配置redis3、创建 RedissonConfig 配

SpringBoot中@Value注入静态变量方式

《SpringBoot中@Value注入静态变量方式》SpringBoot中静态变量无法直接用@Value注入,需通过setter方法,@Value(${})从属性文件获取值,@Value(#{})用... 目录项目场景解决方案注解说明1、@Value("${}")使用示例2、@Value("#{}"php

SpringBoot分段处理List集合多线程批量插入数据方式

《SpringBoot分段处理List集合多线程批量插入数据方式》文章介绍如何处理大数据量List批量插入数据库的优化方案:通过拆分List并分配独立线程处理,结合Spring线程池与异步方法提升效率... 目录项目场景解决方案1.实体类2.Mapper3.spring容器注入线程池bejsan对象4.创建

线上Java OOM问题定位与解决方案超详细解析

《线上JavaOOM问题定位与解决方案超详细解析》OOM是JVM抛出的错误,表示内存分配失败,:本文主要介绍线上JavaOOM问题定位与解决方案的相关资料,文中通过代码介绍的非常详细,需要的朋... 目录一、OOM问题核心认知1.1 OOM定义与技术定位1.2 OOM常见类型及技术特征二、OOM问题定位工具

基于 Cursor 开发 Spring Boot 项目详细攻略

《基于Cursor开发SpringBoot项目详细攻略》Cursor是集成GPT4、Claude3.5等LLM的VSCode类AI编程工具,支持SpringBoot项目开发全流程,涵盖环境配... 目录cursor是什么?基于 Cursor 开发 Spring Boot 项目完整指南1. 环境准备2. 创建

Spring Security简介、使用与最佳实践

《SpringSecurity简介、使用与最佳实践》SpringSecurity是一个能够为基于Spring的企业应用系统提供声明式的安全访问控制解决方案的安全框架,本文给大家介绍SpringSec... 目录一、如何理解 Spring Security?—— 核心思想二、如何在 Java 项目中使用?——

SpringBoot+RustFS 实现文件切片极速上传的实例代码

《SpringBoot+RustFS实现文件切片极速上传的实例代码》本文介绍利用SpringBoot和RustFS构建高性能文件切片上传系统,实现大文件秒传、断点续传和分片上传等功能,具有一定的参考... 目录一、为什么选择 RustFS + SpringBoot?二、环境准备与部署2.1 安装 RustF

springboot中使用okhttp3的小结

《springboot中使用okhttp3的小结》OkHttp3是一个JavaHTTP客户端,可以处理各种请求类型,比如GET、POST、PUT等,并且支持高效的HTTP连接池、请求和响应缓存、以及异... 在 Spring Boot 项目中使用 OkHttp3 进行 HTTP 请求是一个高效且流行的方式。

java.sql.SQLTransientConnectionException连接超时异常原因及解决方案

《java.sql.SQLTransientConnectionException连接超时异常原因及解决方案》:本文主要介绍java.sql.SQLTransientConnectionExcep... 目录一、引言二、异常信息分析三、可能的原因3.1 连接池配置不合理3.2 数据库负载过高3.3 连接泄漏