前置知识:
在HotSpot虚拟机中,对象在内存中存储可分为三块区域:
- 对象头:有MarkWord和Klass Word组成
- 实例数据:里面主要是成员变量
- 对齐填充:不是8的整数倍,则填充
CAS:
Compare and Swap是Java中的一种重要的并发控制机制,属于乐观锁范畴(自旋锁重试机制,就算别的线程修改了,可以重新来一遍)。CAS操作包含三个操作数:内存位置(V)、预期原值(A)和新值(B)。其基本原理是,先读取内存中的值,然后比较该值是否等于期望值,如果相等则将内存中的值更新为新值,否则不做任何操作。这个比较和更新的操作是原子性的,因此可以在多线程环境下保证数据的一致性和完整性。底层一般为native类型,由C++或C实现。
正文如下:
java中sychronized关键字(悲观锁)有3种锁类型
- 轻量级锁:对应不同线程交替执行持有锁,线程加锁的时间段不同,也就是说没有竞争,轻量级锁修改了对象头的锁标志,相对重量级锁性能提升了很多,每次都是CAS操作,保证了原子性。每个线程的栈帧都会包含一个Lock Record的结构,内部可以存储锁定对象的Mark Word,让Lock Record中的Object reference指向锁对象,并尝试用CAS操作来将该对象的Mark Word更新为指向Lock Record的指针。这样,当对象被轻量级锁定时,其Mark Word实际上指向的是Lock Record。简而言之,Lock Record是Java轻量级锁机制中的一个组成部分,用于在锁定对象时记录相关信息,从而实现线程安全的并发控制。
- 偏向锁:对应一段很长时间内只被一个线程使用锁,在第一次获取锁时,会有一个CAS操作,之后线程再获取锁,只需判断mark word是否是自己的线程id即可,而不是执行开销较大的CAS命令。
- 重量级锁:适用于多个线程竞争比较激烈的情况,底层用Monitor实现,里面涉及到用户态和内核态的切换,进程的上下文切换,实现成本较高,性能比较低。
需要注意的是,这些锁状态并不是直接暴露给Java程序员的,而是JVM内部根据线程竞争情况和优化策略自动调整的。一般Java程序员通常只需关注synchronized关键字的使用。