synchronized 锁是 Java 中用于实现线程同步的关键字。它提供了一种简单而有效的方式来确保多个线程之间的互斥访问。底层原理可以通过 Java 的内存模型和对象监视器锁(Monitor Lock)来理解。
Monitor结构如下:
在 Java 的内存模型中,每个对象都有一个与之关联的 Monitor 对象,这个 Monitor 对象是用来实现对象的锁机制的。通过 synchronized 关键字对一个方法或代码块进行修饰,就会使用对象的 Monitor 对象来实现锁。
当一个线程进入 synchronized 修饰的代码块时,它需要首先获得对象的 Monitor 锁。如果该 Monitor
锁当前没有被其他线程占用,则该线程可以顺利获取锁并执行代码块中的内容。如果该 Monitor
锁已经被其他线程占用,则该线程就会被阻塞,直到获取到锁为止。当一个线程获取到锁后,在执行完 synchronized 代码块后会释放这个锁,这样其他线程就可以获取到锁,并继续执行。
synchronized 锁的底层原理是通过 Java 对象头中的一些标志位来实现的。当一个线程获取锁时,会将对象的 mark word
中的一些标志位设置为当前线程的
ID,并且将对象的等待队列中的其他线程阻塞。当线程释放锁时,会将标志位清空,并唤醒等待队列中的一个线程继续执行。
需要注意的是,在 Java 6 之前,synchronized 锁的实现是重量级锁,使用操作系统的互斥量来实现。但是在 Java 6 中,引入了偏向锁、轻量级锁和重量级锁的概念,使得锁的获取和释放过程更加高效。这些优化机制使得 synchronized 锁的性能有了很大的提升。
总结起来,synchronized 锁的底层原理是通过对象的 Monitor 锁来实现线程同步,当一个线程获取锁时,会将对象的标志位设置为当前线程的 ID,并将其他线程阻塞,当线程释放锁时,会将标志位清空,并唤醒等待队列中的一个线程继续执行。