synchronized
1、定义:
synchronized:是一种互斥锁,一次只能允许一个线程进入被锁住的代码块;
2、场景:
(1)修饰实例方法,对应锁是对象实例
(3)修饰代码块,对应锁是传入synchronized的对象实例
3、原理:
从反编译来看:
修饰方法时,编译器会生成ACC_SYNCHRONIZED关键字来标识;
修饰代码块时,会依赖 monitorenter 和 monitorexit 指令
前置知识:
不管是修饰什么,对应的锁都是一个对象;在内存中,对象又分为三部分:对象头,对象实际数据、对齐填充;
其中我们需要重点关注对象头中的 MarkWord 的信息,他会记录对象关于锁的信息;每个对象会存在一个与之对应的monitor对象,monitor中存储着当前持有锁的线程和等待锁的线程队列
Mark Word对锁的状态记录一共有4种:无锁、偏向锁、轻量级锁和重量级锁
无锁
偏向锁:Jvm认为只有某个线程会执行同步代码,MarkWord会直接记录线程的id;只要线程进来,就会对比线程id,如果相等则获取得到锁,执行同步代码;如果id不同,则用CAS尝试修改线程id,如果修改成功,则可以获取得到锁,执行同步代码;如果修改失败,则说明有竞争环境,撤销偏向锁,升级为轻量锁;
轻量级锁:线程会在栈帧下创建LockRecord,并拷贝MarkWord信息,有一个onwer指针指向加锁的对象;当线程执行到同步代码,尝试用CAS将MarkWord指向到线程栈帧的LockRecord,如果成功,则获取轻量锁;如果失败,则自旋(重试),自旋一定程度后,升级到重量级锁;
重量级锁:monitor对象会存储当前进入线程的id,设置MarkWord的monitor地址,将阻塞的线程存储在monitor的等待线程队列中;他加锁依赖操作系统的mutex指令,需要用户态和内核态切换,性能损耗十分明显;(JDK 1.6之前是重量级锁)
引入了偏向锁和轻量级锁,就是为了在不同的使用场景使用不同的锁,进而提高效率。锁只有升级,没有降级
不同锁场景:
(1)只有一个线程进入临界区,使用偏向锁;
(2)多个线程交替进入临界区,使用轻量级锁;
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律