ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

问十四:说说synchronized的膨胀方向?

2019-05-02 16:54:17  阅读:228  来源: 互联网

标签:加锁 synchronized 线程 轻量级 自旋 膨胀 十四 偏向 内存


synchronized的四种状态

无锁、偏向锁、轻量级锁、重量级锁

锁膨胀方向无锁→偏向锁→轻量级锁→重量级锁

 

偏向锁:减少同一线程获取锁的代价

多数情况下,锁不存在多线程竞争,总是由同一线程获得

如果一个线程获得了锁,那么锁就进入偏向模式,此时Mark Word的结构就变成了偏向锁结构,当该线程再次请求锁时,无需再做任何同步操作,获取锁的过程只需要检测Mark Word的锁标记位为偏向锁以及当前线程id等于Mark Word的ThreadID即可,节省了大量有关申请锁的操作

轻量级锁:

由偏向锁升级而来,偏向锁运行在一个线程进入同步代码快的情况下,当第二个线程加入锁争用的时候,偏向锁会升级为轻量级锁

适用于线程交替执行同步块的情况下,加锁解锁使用到CAS操作

重量级锁:

存在同一时间访问同一锁的情况,就会导致轻量级锁膨胀为重量级锁

直接阻塞线程

锁的内存语义:

线程释放锁的时候,java内存模型会把线程对应的本地内存中的共享变量刷新到主内存中

线程获取锁的时候,java内存模型就会把该线程对应的本地内存置为无效,从而使得被监视器保护的临界区代码必须从主存中读取共享变量

各类锁的优缺点

 

其他优化示例:

自旋锁

多数情况下,共享数据的锁定状态持续时间较短,切换线程会带来大量的系统资源消耗

通过让线程执行忙循环来等待锁的释放,不让出CPU

缺点:若锁被其他线程长时间占用,会带来许多性能上的开销,因为在线程自旋的时候,会始终占用CPU的时间片,浪费资源。但是可以让线程在执行忙循环一定次数后停止,可以通过PreBlockSpin来进行修改

自适应自旋锁

自旋的次数不固定,由前一次在同一个锁上的自旋时间以及锁的拥有者的状态来绝定。(比如,如果上一次自旋获得可锁,那么JVM会认为这一次也很有可能能够获取到锁,所以减少锁忙循环的次数,如果很少获得锁,那么以后可能会减少甚至消除锁循环)

锁消除

JIT编译时,对运行上下文进行扫描,去除不可能存在竞争的锁

比如StringBuffer是线程安全的,但是由于stringBuffer只会在append方法中使用,因此它不可能是共享的资源,JVM会自动消除内部的锁

锁粗化

通过扩大加锁的范围,避免反复的加锁解锁

由于反复使用了append这个同步方法,JVM就会自动识别到,并且将加锁的范围加到整个加锁方法的外部,就只需要加一次锁

 

标签:加锁,synchronized,线程,轻量级,自旋,膨胀,十四,偏向,内存
来源: https://blog.csdn.net/qq_18657175/article/details/89762534

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有