详解synchronized关键字(无锁、偏向锁、轻量级锁(自旋锁)、重量级锁四种锁状态)-多线程与高并发

目录

1、CAS(compare and swap)

2、synchronized的底层实现

(1)synchronized锁的状态

(2)一个对象的内存布局(hotspot实现)

(3)markword

(4)synchronized锁状态介绍

(5)用Java Object Layout研究锁升级过程中Markword随锁状态发生的变化

3、synchronized锁的优化与注意点

(1)粒度

(2)final关键字


1、CAS(compare and swap)

CAS(compare and swap):关键是要保证compare和swap两个操作执行不被打断,保证CAS为原子操作。在汇编语言层次,如果操作系统是多cpu的,对CAS操作进行了加锁操作(单cpu由于同一时间只有一个进程对某个数据或内存进行操作,所以没必要加锁)。

lock cmpxchg 指令

 

2、synchronized的底层实现

(1)synchronized锁的状态

JDK早期,synchronized 叫做重量级锁, 因为申请锁资源必须通过内核系统调用。即通过操作系统内核调用进行加锁和解锁,加锁和解锁占用时间过长,线程多了加锁解锁就更频繁了,影响程序性能。(此处的内核调用主要涉及用户态到内核态的切换)

后来为了优化,针对线程的多少进行分层次的不同锁处理,而且尽可能的在用户态完成加锁,减少进行内核态加锁和解锁的操作
。这就是后来的改进升级。

   改进后的synchronized,针对线程的多少而切换不同的锁状态。锁的状态包括无锁态(new)、偏向锁、轻量级锁(自旋锁)、重量级锁(内核级别)。 而这几种锁状态都记录在sync (object)的object中。

(2)一个对象的内存布局(hotspot实现)


一个对象的内存布局(hotspot实现)分为markword(固定8字节)、类型指针(klasspoint固定4字节)、成员变量、有时为了保证字节对齐有空区域进行补齐占位。

字节对齐(字节总数保证是8的整数倍)

  • markword: 用于存储对象自身的运行时数据,如哈希码(HashCode)、GC分代年龄、锁状态标志、线程持有的锁、偏向线程ID、偏向时间戳等等。一般占用8字节。
  • klasspoint: 固定长度4byte, 指定该对象的class类对象(默认使用-XX:+UseCompressedClassPointers 参数进行压缩,可使用-XX:-UseCompressedClassPointers关闭,则该字段在64位jvm下占用8个字节;可使用java -XX:+PrintCommandLineFlags -version 命令查看默认的或已设置的jvm参数);
  • 基本变量:用于存放java八种基本类型成员变量,以4byte步长进行补齐,使用内存重排序优化空间;
  • 引用变量:存放对象地址,如String,Object;占用4个字节,64位jvm上默认使用-XX:+UseCompressedOops进行压缩,可使用-XX:-UseCompressedOops进行关闭,则在64位jvm上会占用8个字节;
  • 补齐:对象大小必须是8byte的整数倍,用来补齐字节数。Object o = new Object() 在内存中占用16个字节,其中最后4个是补齐;
  • 数组长度:如果是数组,额外占用固定4byte存放数组长度;

(3)markword

markword用于存储对象自身的运行时数据,如哈希码(HashCode)、GC分代年龄、锁状态标志、线程持有的锁、偏向线程ID、偏向时间戳等等。一般占用8字节。1字节(Byte)=8比特(bit)
 

下图是hotspot中markword的具体分布,不同的锁状态对应不同的值。

  • 2
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值