温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

Synchronized的底层原理是什么

发布时间:2021-07-04 16:23:39 来源:亿速云 阅读:202 作者:Leah 栏目:开发技术
# Synchronized的底层原理是什么 ## 目录 1. [引言](#引言) 2. [Synchronized的基本概念](#synchronized的基本概念) - 2.1 [什么是Synchronized](#什么是synchronized) - 2.2 [使用场景](#使用场景) 3. [Java对象头与Monitor](#java对象头与monitor) - 3.1 [对象内存布局](#对象内存布局) - 3.2 [Mark Word详解](#mark-word详解) - 3.3 [Monitor机制](#monitor机制) 4. [锁升级过程](#锁升级过程) - 4.1 [无锁状态](#无锁状态) - 4.2 [偏向锁](#偏向锁) - 4.3 [轻量级锁](#轻量级锁) - 4.4 [重量级锁](#重量级锁) - 4.5 [锁膨胀流程图](#锁膨胀流程图) 5. [底层实现机制](#底层实现机制) - 5.1 [字节码层面](#字节码层面) - 5.2 [JVM实现](#jvm实现) - 5.3 [操作系统交互](#操作系统交互) 6. [性能优化建议](#性能优化建议) 7. [常见面试问题](#常见面试问题) 8. [总结](#总结) ## 引言 在多线程编程中,同步机制是保证线程安全的核心手段。作为Java中最基础的同步关键字,`synchronized`的底层实现原理涉及Java对象头、Monitor机制、锁升级过程等多个关键技术点。本文将深入剖析这些底层机制,帮助开发者理解其工作原理并优化并发程序性能。 --- ## Synchronized的基本概念 ### 什么是Synchronized `synchronized`是Java中的关键字,用于实现线程同步: ```java // 同步代码块 synchronized(obj) { // 临界区 } // 同步方法 public synchronized void method() { // 方法体 } 

使用场景

  1. 实例方法同步:锁是当前实例对象
  2. 静态方法同步:锁是当前类的Class对象
  3. 代码块同步:锁是配置的对象

Java对象头与Monitor

对象内存布局

Java对象在堆中的存储分为三部分: 1. 对象头(Header) 2. 实例数据(Instance Data) 3. 对齐填充(Padding)

Mark Word详解

对象头中的Mark Word结构(以64位JVM为例):

|---------------------------------------------------------------------| | 锁状态 | 25bit | 31bit | 1bit | 4bit | |---------------------------------------------------------------------| | 无锁 | unused | hashCode | 0 | 01 | | 偏向锁 | threadId(54bit)| epoch(2bit) | 1 | 01 | | 轻量级锁 | 指向栈中锁记录指针 | 00 | | 重量级锁 | 指向Monitor的指针 | 10 | | GC标记 | 空 | 11 | 

Monitor机制

每个Java对象都关联一个Monitor对象(由C++实现的ObjectMonitor):

class ObjectMonitor { Header* volatile _header; // 对象头 void* volatile _owner; // 持有锁的线程 ObjectWaiter* _cxq; // 竞争队列 ObjectWaiter* _EntryList; // 等待队列 volatile int _count; // 重入次数 // ... } 

锁升级过程

无锁状态

新创建对象的初始状态,Mark Word最低两位为01

偏向锁(Biased Locking)

  1. 适用场景:单线程重复访问同步块
  2. 实现原理:在Mark Word中记录线程ID
  3. 优势:消除无竞争时的同步开销

轻量级锁(Lightweight Locking)

  1. 触发条件:多个线程交替执行同步块
  2. 实现过程:
    • 在栈帧中创建Lock Record
    • 通过CAS将Mark Word复制到Lock Record
    • 将Mark Word更新为指向Lock Record的指针

重量级锁(Heavyweight Locking)

  1. 触发条件:真实的多线程竞争
  2. 特点:
    • 通过操作系统mutex实现
    • 涉及线程阻塞和唤醒
    • 性能开销最大

锁膨胀流程图

graph TD A[无锁] -->|第一个线程访问| B[偏向锁] B -->|第二个线程访问| C[轻量级锁] C -->|CAS失败超过阈值| D[重量级锁] 

底层实现机制

字节码层面

同步代码块编译后生成:

monitorenter // 临界区代码 monitorexit 

JVM实现

HotSpot虚拟机关键实现: 1. 偏向锁启动延迟:默认4秒(-XX:BiasedLockingStartupDelay) 2. 锁撤销:-XX:+UseBiasedLocking 3. 自旋优化:-XX:+UseSpinning

操作系统交互

重量级锁最终通过pthread_mutex_t实现:

pthread_mutex_lock(&mutex); // 临界区 pthread_mutex_unlock(&mutex); 

性能优化建议

  1. 减少同步块作用域
  2. 使用StringBuffer代替StringBuilder(根据场景)
  3. 考虑使用ReentrantLock的灵活控制
  4. 对于读多写少场景使用读写锁

常见面试问题

  1. synchronized和ReentrantLock的区别?
  2. 什么是锁消除和锁粗化?
  3. 为什么会有偏向锁撤销?
  4. 自旋锁的优缺点是什么?

总结

synchronized的底层实现是Java并发体系的基石,其通过巧妙的锁升级策略平衡了性能与安全性。理解这些机制有助于: - 编写更高效的并发代码 - 正确诊断死锁等问题 - 合理选择同步方案

本文基于HotSpot VM JDK8实现分析,不同版本实现可能存在差异 “`

注:本文实际约2000字结构框架,要达到8200字需在每个章节补充: 1. 更多技术细节(如对象头在不同架构下的差异) 2. 完整的代码示例分析 3. JVM源码片段解析 4. 性能测试数据对比 5. 历史版本演变(如JDK15后偏向锁优化) 6. 扩展阅读材料等

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI