IT培训-高端面授IT培训机构
云和教育:云和数据集团高端IT职业教育品牌 全国咨询热线:0371-67988003
课程 请选择课程
    校区 请选择校区
      • 华为
        授权培训中心
      • 腾讯云
        一级认证培训中心
      • 百度营销大学
        豫陕深授权运营中心
      • Oracle甲骨文
        OAEP中心
      • Microsoft Azure
        微软云合作伙伴
      • Unity公司
        战略合作伙伴
      • 普华基础软件
        战略合作伙伴
      • 新开普(股票代码300248)
        旗下丹诚开普投资
      • 中国互联网百强企业锐之旗
        旗下锐旗资本投资

      JVM对Java的原生锁做了哪些优化?

      • 发布时间:
        2023-05-31
      • 版权所有:
        云和教育
      • 分享:

      JVM对Java的原生锁(即synchronized关键字)做了许多优化,其中包括:

      1.偏向锁(Biased Locking)

      当一个线程获取锁后,JVM会将锁的对象头标记为偏向锁。此时,该线程可以无需竞争地获取该锁。这种情况下,锁的获取和释放不需要额外的开销,因为偏向锁会记录线程ID,使得在该线程持有锁期间,其他线程无法获取该锁。只有在其他线程尝试获取锁时,才会升级为轻量级锁。

      2.轻量级锁(Lightweight Locking)

      当多个线程争夺锁时,JVM会将锁标记为轻量级锁。此时,JVM会在锁对象的对象头中记录指向线程栈中锁记录的指针,以及用于保存原始对象的指针。这样,当一个线程尝试获取该锁时,JVM会将该线程的栈帧中的锁记录与锁对象头中的指针进行比较。如果相同,则表示该线程已经获得了该锁;否则,JVM会使用CAS操作尝试将锁对象头中的指针指向当前线程的锁记录。如果CAS操作成功,表示当前线程成功获得了锁。否则,表示有其他线程争夺该锁,此时JVM会将锁升级为重量级锁。

      3.重量级锁(Heavyweight Locking)

      当多个线程争夺锁时,如果无法获得锁,则会升级为重量级锁。此时,JVM会使用操作系统的互斥量实现锁。重量级锁的开销非常大,因为需要进行用户态与内核态之间的上下文切换。

      下面是一个简单的代码演示,展示了偏向锁、轻量级锁和重量级锁的使用情况。

      public class SynchronizedDemo {
          private int count = 0;
      
          public synchronized void increment() {
              count++;
          }
      
          public static void main(String[] args) {
              SynchronizedDemo demo = new SynchronizedDemo();
              for (int i = 0; i < 100000; i++) {
                  demo.increment();
              }
              System.out.println(demo.count);
          }
      }

      在这个示例中,我们使用synchronized关键字来对increment()方法进行同步。由于该方法是实例方法,因此锁对象是该实例对象。当多个线程同时访问该方法时,JVM会根据锁的状态来选择使用偏向锁、轻量级锁或重量级锁。具体的选择过程是由JVM内部的锁升级算法来决定的,这里不再详细展开。