返回

剖析偏向锁升级到轻量级锁的运作机制

后端

在软件开发领域,并发编程是一个令人兴奋而又充满挑战的话题。为了协调多个线程之间的访问和操作,Java提供了synchronized,它可以对代码块或方法进行同步,确保只有一个线程能够执行这些代码。在synchronized的背后,隐藏着三种不同的锁机制:偏向锁、轻量级锁和重量级锁。其中,偏向锁和轻量级锁都是为了提高锁获取的性能而引入的优化手段。

偏向锁

偏向锁是一种非常轻量级的锁,它适用于只有一个线程访问共享资源的情况。当一个线程第一次访问一个对象时,虚拟机会将该对象的锁标记为偏向锁,并将该线程的ID记录在锁记录中。这样,当该线程再次访问该对象时,虚拟机就不需要再进行锁竞争,可以直接进入临界区。

偏向锁的优点是开销非常小,因为它不需要进行任何锁竞争。然而,偏向锁也有一个缺点,那就是它只能用于只有一个线程访问共享资源的情况。如果有多个线程同时访问共享资源,那么偏向锁就会失效,虚拟机需要使用轻量级锁或重量级锁来进行同步。

轻量级锁

轻量级锁也是一种轻量级的锁,但它适用于多个线程同时访问共享资源的情况。当一个线程第一次访问一个对象时,虚拟机将该对象的锁标记为轻量级锁,并将该线程的ID记录在锁记录中。这样,当其他线程访问该对象时,虚拟机就会检查该锁是否已经被另一个线程持有。如果锁已经被持有,那么该线程就会进入等待队列,等待锁释放。

轻量级锁的优点是开销比重量级锁小,因为它不需要进行任何内存分配。然而,轻量级锁也有一个缺点,那就是它可能导致线程饥饿。如果一个线程长时间持有锁,那么其他线程就可能一直处于等待状态,无法访问共享资源。

偏向锁升级到轻量级锁的过程

当一个线程第一次访问一个对象时,虚拟机会将该对象的锁标记为偏向锁。如果该线程再次访问该对象,那么虚拟机就会直接进入临界区。但是,如果其他线程也访问该对象,那么偏向锁就会失效,虚拟机需要使用轻量级锁或重量级锁来进行同步。

偏向锁升级到轻量级锁的过程如下:

  1. 当一个线程第一次访问一个对象时,虚拟机会将该对象的锁标记为偏向锁,并将该线程的ID记录在锁记录中。
  2. 如果该线程再次访问该对象,那么虚拟机就会直接进入临界区。
  3. 但是,如果其他线程也访问该对象,那么偏向锁就会失效,虚拟机需要使用轻量级锁或重量级锁来进行同步。
  4. 虚拟机首先会尝试使用轻量级锁。轻量级锁的开销比重量级锁小,因为它不需要进行任何内存分配。
  5. 如果轻量级锁无法获取成功,那么虚拟机就会使用重量级锁。重量级锁的开销最大,因为它需要进行内存分配。

总结

偏向锁和轻量级锁都是为了提高锁获取的性能而引入的优化手段。偏向锁适用于只有一个线程访问共享资源的情况,轻量级锁适用于多个线程同时访问共享资源的情况。偏向锁升级到轻量级锁的过程是自动进行的,不需要程序员手动干预。