synchronized 是Java中的一个关键字,用来做线程同步同时也保证了数据可见性。
在我看来,锁对象像是令牌,拥有这个令牌的线程可以进行一些操作,当该线程操作完后就会将令牌给下一个。
锁对象
synchronized的锁对象根据使用方式的不同而不同
- 加在普通方法前,锁对象是该实例对象,也就是this
- 加在静态代码块前锁对象是当前类的Class对象
- 使用同步代码块时锁对象是指定的对象
锁存储的位置
在对象头中一个叫Mark Word的区域,在不加锁的情况下对象头中存储的是该对象的hashcode、分代年龄(也就是经历了几次垃圾回收)、标志位。如图(以32位为例)
![技术分享图片]()
锁升级
从JDK1.6开始synchronized存在锁升级的概念,因为一开始就使用重量级锁会使效率严重下降。所以根据线程竞争锁的情况不同分成不同的锁。
- 无锁状态:就是没有锁,此时没有线程调用同步代码
- 偏向锁:由上图可看到在偏向锁状态下Mark Word存储的是偏向的线程ID,也就是哪个线程拥有锁。当由线程过来使用时,会使用CAS将该ID指向自己,如果修改成功就继续运行,修改不成功就升级为轻量级锁
- 轻量级锁:线程在申请轻量级锁时会现在栈帧中开辟用于存储锁记录Lock Record的空间,然后将锁对象的Mark Word复制储存在锁记录中,然后使用CAS将mark word中的栈帧指向该记录,若是失败多次则升级为重量级锁。解锁过程时是换回来,也是使用CAS,如果失败说明存在锁竞争,升级为重量级锁
- 重量级锁:不可撤销回轻量级锁。内置锁在Java中被抽象为监视器锁(monitor)。在JDK 1.6之前,监视器锁可以认为直接对应底层操作系统中的互斥量(mutex)。这种同步方式的成本非常高,包括系统调用引起的内核态与用户态切换、线程阻塞造成的线程切换等,效率没有CAS高。
来张网上的图

synchronized 基本理解
原文:https://www.cnblogs.com/clion/p/14116808.html