java中锁的优化方法
发表于:2024-11-28 作者:千家信息网编辑
千家信息网最后更新 2024年11月28日,这篇文章主要讲解了"java中锁的优化方法",文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习"java中锁的优化方法"吧!1)锁消除概念:JVM在JIT编译
千家信息网最后更新 2024年11月28日java中锁的优化方法
这篇文章主要讲解了"java中锁的优化方法",文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习"java中锁的优化方法"吧!
1)锁消除
概念:JVM在JIT编译(即时编译)时,通过对运行上下文的扫描,去除掉那些不可能发生共享资源竞争的锁,从而节省了线程请求这些锁的时间。举例: StringBuffer的append方法是一个同步方法,如果StringBuffer类型的变量是一个局部变量,则该变量就不会被其它线程所使用,即对局部变量的操作是不会发生线程不安全的问题。 在这种情景下,JVM会在JIT编译时自动将append方法上的锁去掉。
2)锁粗化
概念:将多个连续的加锁、解锁操作连接在一起,扩展成一个范围更大的锁,即将加锁的粒度放大。举例:在for循环里的加锁/解锁操作,一般需要放到for循环外。
3)使用偏向锁和轻量级锁
说明: 1)java6为了减少获取锁和释放锁带来的性能消耗,引入了偏向锁和轻量级锁。 2)锁一共有4种状态,级别从低到高依次是:无锁状态、偏向锁、轻量级锁、重量级锁。 3)锁的状态会随着竞争情况逐渐升级,并且只可以升级而不能降级。 【偏向锁】 1)背景:大多数情况下,锁不仅不存在多线程竞争,而且总是由同一线程多次获得,为了让线程获得锁的代价更低而引入了偏向锁。 2)概念:核心思想就是锁会偏向第一个获取它的线程,如果在接下来的执行过程中没有其它的线程获取该锁,则持有偏向锁的线程永远不需要同步。 3)目的:偏向锁实际上是一种优化锁,其目的是为了减少数据在无竞争情况下的性能损耗。 4)原理: 1>当一个线程访问同步块并获取锁时,会在对象头和栈帧中的锁记录里存储锁偏向的线程ID。 2>以后该线程在进入和退出同步块时就不需要进行CAS操作来加锁和解锁,只需简单地判断一下对象头的Mark Word里是否存储着指向当前线程的偏向锁。 5)偏向锁的获取: 1>访问Mark Word中偏向锁的标识位是否为1,如果是1,则确定为偏向锁。 说明: [1]如果偏向锁的标识位为0,说明此时是处于无锁状态,则当前线程通过CAS操作尝试获取偏向锁,如果获取锁成功,则将Mark Word中的偏向线程ID设置为当前线程ID;并且将偏向标识位设为1。 [2]如果偏向锁的标识位不为1,也不为0(此时偏向锁的标识位没有值),说明发生了竞争,偏向锁已经膨胀为轻量级锁,这时使用CAS操作尝试获得锁。 2>如果是偏向锁,则判断Mark Word中的偏向线程ID是否指向当前线程,如果偏向线程ID指向当前线程,则表明当前线程已经获取到了锁; 3>如果偏向线程ID并未指向当前线程,则通过CAS操作尝试获取偏向锁,如果获取锁成功,则将Mark Word中的偏向线程ID设置为当前线程ID; 4>如果CAS获取偏向锁失败,则表示有竞争。当到达全局安全点时(在这个时间点上没有正在执行的字节码),获得偏向锁的线程被挂起,偏向锁升级为轻量级锁,然后被阻塞在安全点的线程继续往下执行同步代码。 6)偏向锁的释放: 1>当其它的线程尝试获取偏向锁时,持有偏向锁的线程才会释放偏向锁。 2>释放偏向锁需要等待全局安全点(在这个时间点上没有正在执行的字节码)。 3>过程: 首先暂停拥有偏向锁的线程,然后检查持有偏向锁的线程是否活着,如果线程不处于活动状态,则将对象头设置成无锁状态, 如果线程还活着,说明此时发生了竞争,则偏向锁升级为轻量级锁,然后刚刚被暂停的线程会继续往下执行同步代码。 7)优点:加锁和解锁不需要额外的消耗,和执行非同步方法相比仅存在纳秒级的差距 8)缺点:如果线程间存在锁竞争,锁撤销会带来额外的消耗。 9)说明: 1)偏向锁默认在应用程序启动几秒钟之后才激活。 2)可以通过设置 -XX:BiasedLockingStartupDelay=0 来关闭延迟。 3)可以通过设置 -XX:-UseBiasedLocking=false 来关闭偏向锁,程序默认会进入轻量级锁状态。(如果应用程序里的锁大多情况下处于竞争状态,则应该将偏向锁关闭) 【轻量级锁】 1)原理: 1>当使用轻量级锁(锁标识位为00)时,线程在执行同步块之前,JVM会先在当前线程的栈桢中创建用于存储锁记录的空间,并将对象头中的Mark Word复制到锁记录中(注:锁记录中的标识字段称为Displaced Mark Word)。 2>将对象头中的MarkWord复制到栈桢中的锁记录中之后,虚拟机将尝试使用CAS将对象头中Mark Word替换为指向该线程虚拟机栈中锁记录的指针,此时如果没有线程占有锁或者没有线程竞争锁,则当前线程成功获取到锁,然后执行同步块中的代码。 3>如果在获取到锁的线程执行同步代码的过程中,另一个线程也完成了栈桢中锁记录的创建,并且已经将对象头中的MarkWord复制到了自己的锁记录中,然后尝试使用CAS将对象头中的MarkWord修改为指向自己的锁记录的指针,但是由于之前获取到锁的线程已经将对象头中的MarkWord修改过了(并且现在还在执行同步体中的代码,即仍然持有着锁),所以此时对象头中的MarkWord与当前线程锁记录中MarkWord的值不同,导致CAS操作失败,然后该线程就会不停地循环使用CAS操作试图将对象头中的MarkWord替换为自己锁记录中MarkWord的值,(当循环次数或循环时间达到上限时停止循环)如果在循环结束之前CAS操作成功,那么该线程就可以成功获取到锁,如果循环结束之后依然获取不到锁,则锁获取失败,对象头中的MarkWord会被修改为指向重量级锁的指针,然后这个获取锁失败的线程就会被挂起,阻塞了。 4>当持有锁的那个线程执行完同步体之后,使用CAS操作将对象头中的MarkWord还原为最初的状态时(将对象头中指向锁记录的指针替换为Displaced Mark Word ),发现MarkWord已被修改为指向重量级锁的指针,因此CAS操作失败,该线程会释放锁并唤起阻塞等待的线程,开始新一轮夺锁之争,而此时,轻量级锁已经膨胀为重量级锁,所有竞争失败的线程都会阻塞,而不是自旋。 自旋锁: 1)所谓自旋锁,就是让没有获得锁的进程自己运行一段时间自循环(默认开启),但是不挂起线程。 2)自旋的代价就是该线程会一直占用处理器如果锁占用的时间很短,自旋等待的效果很好,反之,自旋锁会消耗大量处理器资源。 3)因此,自旋的等待时间必须有一定限度,超过限度还没有获得锁,就要挂起线程。 优点:在没有多线程竞争的前提下,减少传统的重量级锁带来的性能损耗。 缺点:竞争的线程如果始终得不到锁,自旋会消耗cpu。 应用:追求响应时间,同步块执行速度非常快。 【重量级锁】 说明: 1)java6之前的synchronized属于重量级锁,效率低下,因为monitor是依赖操作系统的Mutex Lock(互斥量)来实现的。 2)多线程竞争锁时,会引起线程的上下文切换(即在cpu分配的时间片还没有用完的情况下进行了上下文切换)。 3)操作系统实现线程的上下文切换需要从用户态转换到核心态,这个状态之间的转换需要相对较长的时间,时间成本相对较高。 4)在互斥状态下,没有得到锁的线程会被挂起阻塞,而挂起线程和恢复线程的操作都需要从用户态转入内核态中完成。 优点:线程竞争不使用自旋,不会消耗cpu。 缺点:线程阻塞,响应时间缓慢。 应用:追求吞吐量,同步块执行速度较长
感谢各位的阅读,以上就是"java中锁的优化方法"的内容了,经过本文的学习后,相信大家对java中锁的优化方法这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是,小编将为大家推送更多相关知识点的文章,欢迎关注!
线程
竞争
对象
同步
时间
状态
轻量
轻量级
指向
循环
方法
标识
情况
重量
重量级
尝试
消耗
阻塞
成功
代码
数据库的安全要保护哪些东西
数据库安全各自的含义是什么
生产安全数据库录入
数据库的安全性及管理
数据库安全策略包含哪些
海淀数据库安全审计系统
建立农村房屋安全信息数据库
易用的数据库客户端支持安全管理
连接数据库失败ssl安全错误
数据库的锁怎样保障安全
滨州oa办公软件开发
数据库连接池的方法
怎么隐藏网站服务器ip啊
pi数据库登录
人工管理数据库技术应用背景
数据库安全性考虑
软件开发延期补充协议
山东中熙网络技术公司位置
华为公司从青阳建数据库
湖北国际网络安全维护收费标准
技嘉m68m支持服务器内存吗
侣程网络技术有限公司
中国芯片服务器上市公司
怎么没有显示查看数据库
粤教版 网络技术应用
信息传输与网络技术
网络安全干货资源
海迅网络技术有限公司
寿光市网络安全科人员
软件开发工具成本不高
属于网络技术的是
泰州应用软件开发创新服务
缓存如何与数据库同步问题
三级数据库可以考c吗
图数据库系统原型图
钱宝网络技术有限公司
辽阳建江网络技术
北京志成网络技术有限公司
服务器安装管理流程图
ceic数据库怎么转换中文版