前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >synchronized与volatile关键字的实现原理

synchronized与volatile关键字的实现原理

原创
作者头像
天下之猴
发布2024-09-18 10:18:55
1140
发布2024-09-18 10:18:55
举报
文章被收录于专栏:笔/面试系列

synchronized

作用域

  • 作用于实例方法,静态方法(类方法),与代码块上,采用悲观锁,当有线程执行到相关资源是,其他线程会被阻塞
  • 保证原子性,有序性,可见性

实现原理

synchronized修饰于代码片段和静态方法,对于带代码片段或者非静态方法,synchronized是通过头对象中的MarkWord的信息来判断,MarkWord中有锁的类型,锁的地址等信息,对于静态方法,通过.Class文件来判断是否加锁.

在jdk1.6之前synchronized实现的方式就是重量锁,即通过操作系统的互斥量来实现加锁,在1.6之后出现了偏向锁,轻量锁,重量锁仍保留,作为等级最高的锁,锁的升级通过由JVM根据多线程下,等待线程的等待时间来判断是否升级,该参数可以进行手动修改

偏向锁,MarkWord字段存储的是线程ID,当有线程占用资源时,将线程id记录到MarkWord,其他线程访问资源时,发现MarkWord字段有值就会执行空循环等待(空循环不会导致阻塞,线程执行起来效率更高),当同一线程多次请求时,无需任何操作,效率得到提升,如果多线程情况下,锁的竞争激烈,那么该锁不适用

轻量锁,MarkWord字段储存的是锁的地址,锁存储在线程的栈帧中,如果其他线程等待时间过长,那么将会进入队列中,锁升级为重量级锁,同时采用非公平锁,其他线程过来之后也是等待一段时间在进队列,如果在等待的时间中,锁被释放,那么该线程将会优先执行,因为总体效率更高

自旋锁,轻量级锁失败后,虚拟机为了避免线程真实地在操作系统层面挂起,还会进行一项称为自旋锁的优化手段。这是基于在大多数情况下,线程持有锁的时间都不会太长,如果直接挂起操作系统层面的线程可能会得不偿失,毕竟操作系统实现线程之间的切换时需要从用户态转换到核心态,这个状态之间的转换需要相对比较长的时间,时间成本相对较高,因此自旋锁会假设在不久将来,当前的线程可以获得锁,因此虚拟机会让当前想要获取锁的线程做几个空循环(这也是称为自旋的原因),一般不会太久,可能是50个循环或100循环,在经过若干次循环后,如果得到锁,就顺利进入临界区。如果还不能获得锁,那就会将线程在操作系统层面挂起,这就是自旋锁的优化方式,这种方式确实也是可以提升效率的。最后没办法也就只能升级为重量级锁了。

重量级锁,通过操作系统层面的互斥量来实现

volatile

作用域

作用于变量上

实现原理

volatile的特性为可见性和有序性,当一个线程对volatile修饰变量进行写操作时,jvm会立即将该变量强制刷入主内存中,当其他变量读取值时,会直接从主内存中读取

通过禁止指令重排保证有序性,具体实现是通过内存屏障来实现的,在每一条指令前后加上屏障指令,只有前面的指令执行完后才能执行后面的指令

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • synchronized
    • 作用域
      • 实现原理
      • volatile
        • 作用域
          • 实现原理
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档