锁的优化

在前几天的文章: 浅谈Java中的锁:Synchronized、重入锁、读写锁 中我们学习了多线程环境下为了保证线程安全需要加各种各样的锁,但是加锁势必会带来性能的损耗,此篇文章就讨论一下如何优化加锁后的程序

锁优化策略

    1. 减少锁持有时间 

        对一个方法加锁,不如只对需要同步的那几行代码加锁,减少线程持有锁的时间。

    2. 减小锁粒度

        将大对象,拆成小对象进行加锁。例如ConcurrentHashMap采取对segment加锁而不是对整个map加锁,这样只要修改的segment不同,就可以并发的进行。

    3. 锁分离 

        使用我们文章开头提到的文章中所说的读写分离锁或者根据不同的功能进行加锁

    4. 锁粗化 

        策略1要求每个线程持有锁的时间越短越好,但是呢,锁的申请、同步和释放也是需要时间的,所以说如果有频繁的加锁请求时(例如在循环内加锁),最好把多个加锁的请求合并为一个(在循环外加锁),以减少锁的请求及释放的时间。

虚拟机对锁优化做的努力

    1. 锁偏向

       当一个线程获得锁之后,锁就会进入偏向模式。接下来这个线程如果再次请求锁的时候就不需要再做同步操作了。(即:持有该锁的线程在接下来的执行中遇到同步块时不再需要lock和unlock了,直接执行即可)直到另外的线程前来请求的时候锁偏向才会失效。

锁偏向的优化适用于锁竞争不是很强的场景,如果是竞争激烈的场景则偏向锁会一直处于失效状态。

    2. 轻量级锁

        如果偏向锁失败,那么系统会进行轻量级锁的操作,使用CAS操作来尝试加锁。如果轻量级锁失败,才调用系统级别的重量级锁(syncrhoized)来加锁。     

    3. 自旋锁

        为了避免使用重量级锁的巨大消耗,虚拟机在轻量级锁失败膨胀后让当前线程做几个空循环(这就是自旋的来源)来赌这个线程可以在自旋之后获得锁,如果还不能获得锁的话则真实的使用重量级锁了。

    4. 锁消除

        虚拟机在编译时,会对上下文进行扫描,去除那些不可能存在竞争的锁。

    总结

         为了尽量避免使用重量级锁,JVM首先在编译期先消除一些不可能存在竞争的锁。当一个线程获得锁后会对这个线程偏向以保证此线程再次获得锁时可以减少同步所需的时间。偏向锁失败后会尝试轻量级锁,轻量级锁尝试使用CAS操作来获得锁。如果轻量级锁失败,JVM同样会赌一下此线程很可能很快获得锁,就会尝试自旋锁,将线程做几个空循环。如果自旋锁也失败,那么就只能升级成重量级锁了。

640?wx_fmt=gif

640?wx_fmt=jpeg

 收藏转发好看再走呗!

640?wx_fmt=gif

【路径规划】(螺旋)基于A星全覆盖路径规划研究(Matlab代码实现)内容概要:本文围绕“基于A星算法的全覆盖路径规划”展开研究,重点介绍了一种结合螺旋搜索策略的A星算法在栅格地图中的路径规划实现方法,并提供了完整的Matlab代码实现。该方法旨在解决移动机器人或无人机在未知或部分已知环境中实现高效、无遗漏的区域全覆盖路径规划问题。文中详细阐述了A星算法的基本原理、启发式函数设计、开放集与关闭集管理机制,并融合螺旋遍历策略以提升初始探索效率,确保覆盖完整性。同时,文档提及该研究属于一系列路径规划技术的一部分,涵盖多种智能优化算法与其他路径规划方法的融合应用。; 适合人群:具备一定Matlab编程基础,从事机器人、自动化、智能控制及相关领域研究的研究生、科研人员及工程技术人员。; 使用场景及目标:①应用于服务机器人、农业无人机、扫地机器人等需要完成区域全覆盖任务的设备路径设计;②用于学习和理解A星算法在实际路径规划中的扩展应用,特别是如何结合特定搜索策略(如螺旋)提升算法性能;③作为科研复现与算法对比实验的基础代码参考。; 阅读建议:建议结合Matlab代码逐段理解算法实现细节,重点关注A星算法与螺旋策略的切换逻辑与条件判断,并可通过修改地图环境、障碍物分布等方式进行仿真实验,进一步掌握算法适应性与优化方向。
优化是指在多线程编程中,通过改进的机制和使用方式来提高程序的性能和并发能力。synchronized关键字是Java中最常用的机制之一,它可以保证同一时间只有一个线程可以进入被synchronized修饰的代码块。下面是一些synchronized优化的方法: 1. 减小的粒度:如果在一个方法中有多个synchronized代码块,可以考虑将这些代码块拆分成多个方法,以减小的粒度。这样可以使得多个线程可以并发执行不同的代码块,提高程序的并发性能。 2. 使用局部变量替代成员变量:在使用synchronized关键字时,尽量使用局部变量而不是成员变量。因为成员变量的访问需要通过对象实例来进行,而局部变量的访问是线程私有的,不需要加锁。 3. 使用同步代码块代替同步方法:在某些情况下,使用同步代码块比使用同步方法更加灵活。同步代码块可以指定的粒度,只对需要同步的代码进行加锁,而不是整个方法。 4. 使用volatile关键字:volatile关键字可以保证变量的可见性和禁止指令重排序,可以在一定程度上替代synchronized关键字。但是需要注意,volatile关键字只能保证单个变量的原子性,不能保证多个操作的原子性。 5. 使用Lock接口:Java提供了Lock接口及其实现类ReentrantLock,相比于synchronized关键字,Lock接口提供了更加灵活的机制。可以手动控制的获取和释放,可以实现公平和非公平,并且支持多个条件变量。 6. 使用读写:如果在多线程环境下,读操作远远多于写操作,可以考虑使用读写ReadWriteLock来提高程序的并发性能。读写允许多个线程同时读取共享数据,但只允许一个线程写入共享数据。 7. 使用并发集合类:Java提供了一些并发集合类,ConcurrentHashMap、ConcurrentLinkedQueue等,它们内部使用了一些优化的技术,可以提高多线程环境下的并发性能。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值