说一说自己对于 synchronized 关键字的理解?
1 个回答
理解一切,没有对错,让花成花,让树成树。古魔`synchronized` 关键字是 Java 中解决多线程环境下资源同步问题的关键技术。它可以保证被它修饰的方法或代码块在任意时刻只能有一个线程执行,从而避免多个线程同时访问共享资源导致的数据不一致问题。 #### 主要特点 1. **互斥性**:`synchronized` 关键字确保了同时只有一个线程可以执行被 `synchronized` 修饰的方法或代码块。其他线程在进入该方法或代码块前必须等待,直到当前线程退出。 2. **可见性**:`synchronized` 不仅保证了互斥性,还能确保在退出 `synchronized` 块或方法时,线程对共享变量的修改对其他线程是可见的。这是因为 `synchronized` 会在进入和退出同步块时分别执行内存屏障,保证变量的变化及时刷新到主内存中。 #### 早期实现和性能问题 在 Java 的早期版本中,`synchronized` 是一种重量级锁,效率较低。这是因为监视器锁(`monitor`)依赖于底层操作系统的 Mutex Lock 实现,而 Java 的线程是映射到操作系统的原生线程之上的。挂起和唤醒线程需要操作系统的协助,而这涉及从用户态到内核态的转换,时间成本较高,因此 `synchronized` 在早期版本中效率较低。 #### 性能优化 从 Java 6 开始,Java 官方对 `synchronized` 进行了大量优化,提高了其性能,使其效率大大提升。主要优化技术包括: 1. **自旋锁和适应性自旋锁**:在短时间的等待中,自旋锁避免了线程的挂起和切换,通过让线程进行忙等待(自旋),从而减少线程切换的开销。适应性自旋锁会根据上一次自旋等待的时间和锁的拥有者的状态来决定是否进行自旋,从而提高效率。 2. **锁消除**:JIT 编译器在运行时,通过对运行上下文的扫描,去除不可能存在共享资源竞争的锁。锁消除的优化主要依赖于逃逸分析技术。 3. **锁粗化**:JVM 会将多个连续的小范围的锁操作合并成一个大的锁操作,从而减少锁的获取和释放次数,提高性能。 4. **偏向锁**:偏向锁是为了在无竞争的情况下进一步提高性能。当一个线程访问同步块并获取锁时,会在对象头和栈帧中存储锁的偏向线程 ID,以后该线程在进入和退出同步块时不需要再进行 CAS 操作来加锁和解锁,从而提高性能。 5. **轻量级锁**:当锁是偏向锁时,被另一个线程所持有时,会膨胀为轻量级锁。轻量级锁使用 CAS 操作代替互斥量,使得加锁和解锁的开销变小。 #### 代码示例 以下是一个简单的 `synchronized` 方法和代码块的示例: ```java public class SynchronizedExample { // synchronized 修饰方法 public synchronized void synchronizedMethod() { // 代码块 } // synchronized 修饰代码块 public void method() { synchronized (this) { // 代码块 } } } ``` ### 总结 - **互斥性**:`synchronized` 确保了同一时间只有一个线程可以执行被修饰的方法或代码块。 - **可见性**:保证了线程对共享变量的修改在退出同步块时对其他线程可见。 - **早期性能问题**:依赖于操作系统的 Mutex Lock,实现线程切换的成本较高。 - **性能优化**:Java 6 之后,引入了自旋锁、适应性自旋锁、锁消除、锁粗化、偏向锁、轻量级锁等技术,大大提升了 `synchronized` 的性能。 通过这些优化,`synchronized` 关键字在保证线程安全的同时,也在性能方面得到了显著提升,使得它在现代 Java 编程中依然是一个非常重要的同步机制。发布于 2024-07-24 02:32 •IP属地 北京举报评论收藏
公众号进入网站体验更佳

