Lock的锁之优化

深入解析dvm_lock_sample:从日志到锁竞争优化 本文深入解析dvm_lock_sample日志在Android系统锁竞争优化中的应用,详细介绍了日志解析技巧、常见锁竞争模式及解决方案。通过实战案例展示如何从日志定位到代码优化,帮助开发者提升系统性能,减少ANR问题。文章还提供了高级分析工具和系统级优化策略,是Android性能调优的实用指南。 阅读详情

Lock / synchronized

Lock锁的基本操作是通过乐观锁实现的,由于Lock锁也会在阻塞时被挂起,依然属于悲观锁

synchronizedLock实现方式JVM层实现Java底层代码实现锁的获取JVM隐式获取lock() / tryLock() / tryLock(timeout, unit) / lockInterruptibly()锁的释放JVM隐式释放unlock()锁的类型非公平锁、可重入非公平锁/公平锁、可重入锁的状态不可中断可中断锁的性能高并发下会升级为重量级锁更稳定

实现原理

Lock锁是基于Java实现的锁,Lock是一个接口
常见的实现类:ReentrantLock、ReentrantReadWriteLock,都是依赖AbstractQueuedSynchronizer(AQS)实现

  1. AQS中包含了一个基于链表实现的等待队列(即CLH队列),用于存储所有阻塞的线程
  2. AQS中有一个state变量,该变量对ReentrantLock来说表示加锁状态
  3. AQS中的CLH队列的所有操作均通过CAS操作实现的

在这里插入图片描述

锁分离优化

ReentrantReadWriteLock

  • ReentrantLock是一个独占锁,同一时间只允许一个线程访问
  • ReentrantReadWriteLock允许多个读线程同时访问,但不允许写线程和读线程、写线程和写线程同时访问
  • ReentrantReadWriteLock内部维护了两把锁,一把用于读操作的ReadLock,一把用于写操作的WriteLock
  • ReentrantReadWriteLock如何保证共享资源的原子性?ReentrantReadWriteLock也是基于AQS实现的
  • 自定义同步器(继承AQS)需要在同步状态state上维护多个读线程和一个写线程的状态
  • ReentrantReadWriteLock利用了高低位,来实现一个整型控制两种状态的功能
  • 将同步状态state切分为两部分,高16位表示读,低16位表示写

获取写锁

  • 一个线程尝试获取写锁时,会先判断同步状态state是否为0
  • 如果state为0,说明暂时没有其他线程获取锁
  • 如果state不为0,说明其它线程获取了锁
  • 当state不为0时,会再去判断同步状态state的低16位(w)是否为0
  • 如果w为0,说明其它线程获取了读锁,此时直接进入CLH队列进行阻塞等待(因为读锁与写锁互斥)
  • 如果w不为0,说明有线程获取了写锁,此时要判断是不是当前线程获取了写锁
  • 如果不是,进入CLH队列进行阻塞等待
  • 如果是,就应该判断当前线程获取写锁是否超过最大次数,如果超过,抛出异常,否则更新同步状态state

在这里插入图片描述

获取读锁

  • 一个线程尝试获取读锁时,同样会先判断同步状态state是否为0
  • 如果state为0,说明暂时没有其他线程获取锁,此时需要判断是否需要阻塞
  • 如果需要阻塞,则进入CLH队列进行阻塞等待
  • 如果不需要阻塞,则CAS更新state为读状态
  • 如果state不为0,说明其它线程获取了锁
  • 当state不为0时,会同步判断同步状态state的低16位
  • 如果存在写锁,直接进入CLH阻塞队列
  • 反之,判断当前线程是否应该被阻塞,如果不应该被阻塞则尝试CAS同步状态,获取成功更新同步锁为读状态

在这里插入图片描述

StampedLock

  1. ReentrantReadWriteLock被很好地应用在读多写少的并发场景中,但会存在写线程饥饿的问题,Java 8引入StampedLock解决了这个问题

  2. StampedLock不是基于AQS实现的,但实现原理与AQS类似,都是基于队列和锁状态

  3. StampedLock有三种模式:写、悲观读、乐观读,StampedLock在获取锁时会返回一个票据stamp

  4. 一个写线程获取写锁的过程中,首先是通过writeLock获取一个票据stamp(表示锁的版本),WriteLock是一个独占锁,同时只能有一个线程可以获取WriteLock
    当一个线程获取WriteLock后,其他请求的线程必须等待
    当没有其他线程持有读锁或者写锁时才可以获得WriteLock

  5. 一个读线程获取读锁的过程中,首先会通过tryOptimisticRead获取一个票据stamp,
    如果当前没有线程持有写锁,会返回一个非0的stamp,
    然后调用validate验证之前调用tryOptimisticRead返回的stamp在当前是否有其他线程持有了写锁,
    如果是,那么validate返回0,升级为悲观锁。

  6. 相对于ReentrantReadWriteLock,StampedLock获取读锁只使用了与或操作进行校验,不涉及CAS操作
    即使第一次乐观锁获取失败,也会马上升级为悲观锁,可以避免一直进行CAS操作而带来的CPU性能消耗问题

  7. 但StampedLock并没有被广泛使用,有几个主要原因
    StampedLock的功能仅仅只是ReadWriteLock的子集
    StampedLock不支持重入!!
    StampedLock的悲观读锁、写锁都不支持条件变量(不符合管程模型)

public class Point {
 private double x, y;
 private final StampedLock lock = new StampedLock();
 public void move(double deltaX, double deltaY) {
 // 获取写锁
 long stamp = lock.writeLock();
 try {
 x += deltaX;
 y += deltaY;
 } finally {
 // 释放写锁
 lock.unlockWrite(stamp);
 }
 }
 double distanceFromOrigin() {
 // 乐观读
 long stamp = lock.tryOptimisticRead();
 // 拷贝变量
 double currentX = x, currentY = y;
 // 判断读期间是否有写操作
 if (!lock.validate(stamp)) {
 // 升级为悲观读
 stamp = lock.readLock();
 try {
 currentX = x;
 currentY = y;
 } finally {
 lock.unlockRead(stamp);
 }
 }
 return Math.sqrt(currentX * currentX + currentY + currentY);
 }
}

小结

  1. 不管使用synchronized同步锁还是Lock同步锁,只要存在锁竞争就会产生线程阻塞,导致线程频繁切换,增加性能消耗

  2. 优化锁的关键:降低锁竞争

synchronized同步锁:减少锁粒度、减少锁占用时间
Lock同步锁:锁分离

Java Lock锁的NUMA架构优化策略 随着服务器从“多核”走向“超多核”(如48核、96核),传统UMA(统一内存访问)架构因内存总线瓶颈逐渐被NUMA取代。但Java开发者在使用Lock锁时,若忽略NUMA特性,可能遇到“线程越跑越慢”的奇怪现象。本文将聚焦Java Lock锁在NUMA架构下的性能瓶颈,详解优化策略,覆盖理论原理、代码实现和实战验证。本文将按照“概念→问题→优化→实战”的逻辑展开:首先用生活案例解释NUMA架构和Java锁的工作原理;然后分析NUMA对锁性能的具体影响;接着讲解4类核心优化策略;最后通过代码实战验证优化效果。 阅读详情

相关推荐

驱动钛丝(SMA)的应用(5)汽车腰托气阀常见问题及解决方案

财哥在前段时间发布的《驱动钛丝(SMA)的应用(1)汽车腰托支撑按摩气阀模块》一文,引发了很多企业的拜访和交流。 目前很多厂家已经启动或正在进行相关研发,同时也遇到了诸如:钛丝选型、驱动位移、响应设计、温度控制、力量设计、点动滞后、铆接工艺、量化生产等问题。

weixin_39168671的博客 1239

Java性能 -- Lock优化

Lock / synchronized Lock锁的基本操作是通过乐观锁实现的,由于Lock锁也会在阻塞时被挂起,依然属于悲观锁 synchronizedLock 实现方式 JVM层实现 Java底层代码实现 锁的获取 JVM隐式获取 lock() / tryLock() / tryLock(timeout, unit) / lockIn...

WANGXIAN2014的博客 244

SOI技术实战:从晶圆结构到芯片性能提升的完整解析

本文深入解析SOI(Silicon on Insulator)技术如何通过独特的三明治晶圆结构提升芯片性能,涵盖从220nm SOI层设计到7nm节点的工艺挑战。详细探讨了埋氧层的绝缘优势、性能提升的物理机制,以及AMD处理器和5G射频中的实战应用,为半导体行业提供关键技术洞见。

wdx0123456的博客 960

Python中的进程池及进程池锁:multiprocessing.Pool及multiprocessing.Manager().Lock()

不过,也不用过于担心,Python虽然不能利用多线程实现多核任务,但可以通过多进程实现多核任务。7、两者最大的不同在于在多进程中,同一个变量,各自有一份拷贝存在于每个进程中,互不影响;如果有很多任务需要执行,池中的进程数量不够,任务就要等待之前的进程执行任务完毕归来,拿到空闲进程才能继续执行。定义一个池子,在里面放上固定数量的进程,有需求来了,就拿一个池中的进程来处理任务。也就是说,进池中进程的数量是固定的,那么同一时间最多有固定数量的进程在运行。多进程中,不同的子进程进程号不同。进程的内存是独立的。...

种一棵树最好的时间是十年前,其次是现在 1785

Altium Designer 18 将Gerber文件逆向转换成PCB(详细记录)

自己看了网上的教程,弄了很久,估计还有不足的地方,但是先把思路理一理(初学AD) 同时遇到了许多问题: 不是AD导出的Gerber估计不能自动识别层 要自己设置层顺序 要有钻孔文件数据制作NC工具(我也不懂是怎么说,就是size尺寸的) 这里记录一下,以防忘记。 正常顺序: 1.新建CAM 2.导入Gerber,选择CAM文件夹下的所有文件导入 3.设置层属性和物理顺序 4.设置NC工具 5.提取网络表 ...

lb_monkey的博客 1万+

基于IC动态加权的机器学习多因子选股策略:从模型融合到实战回测

在量化投资领域,多因子选股模型通过挖掘市场数据中的有效信号来预测股票收益。其核心原理在于利用统计学与机器学习算法,从海量因子中识别出与未来收益具有稳定相关性的特征。这一技术的核心价值在于将主观投资决策转化为系统化、可重复的客观过程,从而在控制风险的前提下追求超额收益。其典型应用场景包括股票阿尔法策略构建、Smart Beta产品设计以及资产配置中的股票筛选环节。本文聚焦于如何通过信息系数(IC)这一关键指标,动态融合Ridge回归、MLP神经网络和随机森林等多个预测模型,构建一个能够自适应市场风格轮动的选股

weixin_34216614的博客 450

Java高并发(五)——Lock优化,提高性能

       前边我们讲了,多线程的世界,多线程的基础操作,多线程协作,多线程管理——线程池。其中多线程为什么麻烦,就因为线程并行操作,对共享资源的争夺,会出现线程安全问题。而我们解决线程安全问题的方案是同步(锁资源,串行使用),串行就会出现性能问题。举个例子:大家在大道上并行前进的几列人(多线程并发),突然遇到河流,只有一个独木桥,大家只能一个个过(锁共享资源,串行使用)。显而易见,时间更多的消...

学会改变自己——才能突破 3581

C/C++ 计算程序运行的时间

C/C++计算程序执行时间的方法,精度依次增加,推荐度也依次增加 1.#include <time.h> clock_t start, finish; double process_interval ; start=clock(); process(); //要计时的程序 finish=clock(); process_interval =(double)(finish-star...

stu_shanghui的博客 1020

深入理解.Net中的锁(一)为什么不建议使用Lock

在CLR Via C#一书中作者说了,他不推荐在任何时候使用lock,说实话,我们在很多时候还是会为了方便,在一些简单的场景中,还是会顺手就使用lock,那么为什么不建议使用lock呢?今天就来详细说说。 先上代码 代码环境为.Net4.6.1,因为.net6中Thread.CurrentThread.Abort()方法被弃用了。 using System; using System.Collections.Generic; using System.Linq; using System.Text; usi

小黄瓜要编程的博客 2372

Miniconda入门:在CentOS上的安装、基本操作、目录结构、卸载

Miniconda是一个 免费的 轻量级的 conda安装程序 它只包含conda、Python、pip、zlib等基础的文件和依赖包 使用conda install命令可从Anaconda存储库中安装额外的conda包 简介 下载 安装 基本操作 虚拟环境的操作 包的操作 目录结构 卸载

ArYe 1万+

基于STM32的智能血氧、心率、体温、血压监测系统

摘要:本文设计了一款基于STM32F103C8T6的多功能健康监测系统,可实时检测血氧、心率、体温和血压四项生理参数。系统集成MAX30102、DS18B20等传感器模块,采用OLED显示和蓝牙无线传输技术,实现一键血压测量、阈值报警及手机APP数据管理功能。硬件设计包含传感器采集、电源管理、显示报警等模块;软件采用模块化架构,实现数据采集处理、蓝牙通讯等功能。测试表明系统测量准确可靠,为家庭健康监测提供了便携解决方案。未来可扩展更多监测参数和智能分析功能。

3254968421的博客 766

.Net 线程安全 (细粒度锁定、无锁机制以及lock)

在多线程操作过程中,最省事的安全操作关键字就是lock,但是这会影响到多线程操作的性能。.NET Framework 4 引入了 System.Collections.Concurrent 命名空间,其中包含多个线程安全且可缩放的集合类。 多个线程可以安全高效地从这些集合添加或删除项,而无需在用户代码中进行其他同步。 编写新代码时,只要将多个线程同时写入到集合时,就使用并发集合类。 简单来说使用上述的对象进行多线程之间操作的时候都能确保线程安全例子中使用一个主线程往队列中写入一些数据,然后分10个线程进行读

iml6yu的博客 1923

AutoSAR配置视频讲解:简介

AutoSAR实验视频讲解:闪烁一颗LED实验【简介】 大家好,欢迎来到雪云飞星的《AutoSAR实验课的视频讲解》专栏。看过《AutoSAR入门到精通系列讲解》的朋友们应该对博主不陌生,有很多朋友加了博主的微信成为了好友,还有朋友约过线下见面,博主很高兴大家能从我的博客中获得一些收获。在专栏里博主挖了很多坑,当时也说过想要录制一个AutoSAR的配置视频教程,素材在20年初就已经录好,中间各种原因足足鸽了一年。当时因为一些技术原因只能通过博客的图文形式展示出来,现在我们剪辑了视频,请了专业的配音,希望以视

雪云飞星的博客 9652

Synchronized与Lock锁的优化方法

Synchronized锁和Lock锁都是Java中常用的同步控制机制。Synchronized锁是Java中最基本的同步控制方式,它简单易用,并且能够满足大部分场景的需求。但是,在竞争激烈或者需要更细粒度控制的场景下,Synchronized锁可能会导致性能下降或者无法满足需求。此时,我们可以使用Lock锁来进行优化,通过可重入锁、公平锁、读写锁等特性来满足不同场景的需求。无论使用哪种同步控制方式,我们都需要避免死锁、竞争等问题,并根据实际情况对锁进行精细化调整,以提高程序的性能和可靠性。

qq_41194023的博客 458

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

lock是乐观锁吗_性能:Lock的锁之优化

Lock / synchronizedLock锁的基本操作是通过乐观锁实现的,由于Lock锁也会在阻塞时被挂起,依然属于悲观锁 synchronizedLock实现方式JVM层实现Java底层代码实现锁的获取JVM隐式获取lock() / tryLock() / tryLock(timeout, unit) / lockInterruptibly()锁的释放JVM隐式释放unlock()锁的类型非...

weixin_36250086的博客 484

RU DOS版、EFI版32bit/64bit BIOS常用工具

DOS版、EFI版的RU工具,可用来查看IO、MEM、PCI、SMBIOS等资源。亲测在EFI SHELL下可用。

多线程之锁优化(中):深入了解Lock同步锁的优化方法

不管使用Synchronized同步锁还是Lock同步锁,只要存在锁竞争就会产生线程阻塞,从而导致线程之间的频繁切换,最终增加性能消耗。因此,如何降低锁竞争,就成为了优化锁的关键。在Synchronized同步锁中,我们了解了可以通过减小锁粒度、减少锁占用时间来降低锁的竞争。在这一讲中,我们知道可以利用Lock锁的灵活性,通过锁分离的方式来降低锁竞争。

echohuangshihuxue的博客 1368

jvm 的锁优化、java 的锁、synchronize 和 lock 接口区别是什么?

如果您有任何问题,请随时提出。- synchronized关键字在底层通过监视器锁(Monitor)实现,每个Java对象都有一个关联的Monitor对象,当线程进入synchronized代码块时,会尝试获取对象的Monitor锁。- synchronized关键字的优点是使用简单,不需要手动释放锁,JVM会自动管理锁的获取和释放。- Lock接口提供了更多的功能,如可重入锁、公平锁、读写锁等,可以更好地满足不同场景的需求。- Lock接口的优点是提供了更多的功能和灵活性,适用于复杂的多线程场景。

EchoYa!的博客 315

性能:Lock的锁之优化

Lock / synchronized Lock锁的基本操作是通过乐观锁实现的,由于Lock锁也会在阻塞时被挂起,依然属于悲观锁 synchronizedLock实现方式JVM层实现Java底层代码实现锁的获取JVM隐式获取lock() / tryLock() / tryLock(timeout, unit) / lockInterruptibly()锁的释放JVM隐式释放unlock()锁的...

sevencuecue的博客 826

Java | 多线程之锁优化(中):深入了解Lock同步锁的优化方法

今天这讲我们继续来聊聊锁优化。上一讲我重点介绍了在 JVM 层实现的 Synchronized 同步锁的优化方法,除此之外,在 JDK1.5 之后,Java 还提供了 L...

sinat_27143551的博客 361

java并发优化之锁lock

一.synchronized的缺陷   synchronized是java中的一个关键字,也就是说是Java语言内置的特性。那么为什么会出现Lock呢?   在上面一篇文章中,我们了解到如果一个代码块被synchronized修饰了,当一个线程获取了对应的锁,并执行该代码块时,其他线程便只能一直等待,等待获取锁的线程释放锁,而这里获取锁的线程释放锁只会有两种情况:   1)获取锁的线程执行完了该代码块,然后线程释放对锁的占有;   2)线程执行发生异常,此时JVM会让线程自动释放锁。   那么如果

swebin的专栏 1291

多线程之锁优化Lock同步锁的优化

在 JDK1.5 之后,Java 还提供了 Lock 同步锁。那么它有什么优势呢? 相对于需要 JVM 隐式获取和释放锁的 Synchronized 同步锁,Lock 同步锁(以下简称 Lock 锁)需要的是显示获取和释放锁,这就为获取和释放锁提供了更多的灵活性。Lock 锁的基本操作是通过乐观锁来实现的,但由于 Lock 锁也会在阻塞时被挂起,因此它依然属于悲观锁。我们可以通过一张图来简单对比下两个同步锁,了解下各自的特点: 从性能方面上来说,在并发量不高、竞争不激烈的情况下,Synchro.

haponchang的博客 352

从源头解析synchronized与Lock锁(对比和实现细节,锁优化、AQS)

synchronized与Lock锁(对比和实现细节) synchronized synchronized关键字在需要原子性、可见性和有序性这三种特性的时候都可以作为其中一种解决方案,看起来是“万能”的。的确,大部分并发控制操作都能使用synchronized来完成。 上面这段话出自《深入理解Java虚拟机》,在并发编程中,经常会用到synchronized,下面来看一下synchronized的...

Jerry1ee 935

java基础总结(九十)--性能:Lock的锁之优化

原文链接 Lock / synchronized Lock锁的基本操作是通过乐观锁实现的,由于Lock锁也会在阻塞时被挂起,依然属于悲观锁 synchronizedLock实现方式JVM层实现Java底层代码实现锁的获取JVM隐式获取lock() / tryLock() / tryLock(timeout, unit) / lockInterruptibly()锁的释放JVM隐式释放unlock()锁的类型非公平锁、可重入非公平锁/公平锁、可重入锁的状态不可中断可中断锁的性能高并发下会升级为重量级锁更

秋天的猿 329

Python 锁竞争优化:在高并发 RAG 服务中减少 asyncio.Lock 的等待时间

asyncio.Lock 的优化围绕一个核心原则:让锁保护的临界区尽可能小、尽可能少。四种优化方向按优先级排:连接池替代单连接(改一行配置)、分片锁替代全局锁(改锁的粒度)、SingleFlight 防惊群(加缓存层)、缩小临界区(重构代码逻辑)。落地路径:先用收集 15 分钟的锁竞争数据,找出竞争率最高的 3 个锁;再按上面的优先级逐项优化;优化后重新测量,确认 p99 锁等待时间降到了可接受的范围。

2401_87746054的博客 4766

educoder 使用线程锁(lock)实现线程同步_性能:Lock的锁之优化

Lock / synchronizedLock锁的基本操作是通过乐观锁实现的,由于Lock锁也会在阻塞时被挂起,依然属于悲观锁synchronizedLock实现方式JVM层实现Java底层代码实现锁的获取JVM隐式获取lock() / tryLock() / tryLock(timeout, unit) / lockInterruptibly()锁的释放JVM隐式释放unlock()锁的类型非公...

weixin_39598135的博客 220

多生产者消费者问题,Lock锁以及懒汉式的优化

public class Demo10 { public static void main(String[] args) { //准备数据 Product1 product = new Product1(); //准备任务 Producer1 producer = new Producer1(product); Consumer1 consumer = new Consumer1(product)...

域清风 369
上一篇: 深入理解MySQL,简历上再说熟悉数据库
下一篇: 面试官,不要再问我三次握手和四次挥手
春来桃花开
博客等级 码龄10年 21粉丝 30原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值