Java 中的 synchronized_javasynchronized用法
Java 中的 synchronized
关键字深度解析
synchronized
是 Java 中最核心的线程同步机制,用于解决多线程环境下的数据竞争和可见性问题。以下是全面解析:
一、synchronized
的三大用法
1. 同步实例方法
public synchronized void increment() { count++; // 锁对象是当前实例(this)}
2. 同步静态方法
public static synchronized void staticMethod() { // 锁对象是类的Class对象(如 MyClass.class)}
3. 同步代码块
public void doSomething() { // 非同步代码 synchronized(lockObject) { // 显式指定锁对象 // 需要同步的代码 }}
二、锁的底层实现
1. 对象头与 Monitor 结构
#mermaid-svg-QiClQA6EyyacKkwY {font-family:\"trebuchet ms\",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-QiClQA6EyyacKkwY .error-icon{fill:#552222;}#mermaid-svg-QiClQA6EyyacKkwY .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-QiClQA6EyyacKkwY .edge-thickness-normal{stroke-width:2px;}#mermaid-svg-QiClQA6EyyacKkwY .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-QiClQA6EyyacKkwY .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-QiClQA6EyyacKkwY .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-QiClQA6EyyacKkwY .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-QiClQA6EyyacKkwY .marker{fill:#333333;stroke:#333333;}#mermaid-svg-QiClQA6EyyacKkwY .marker.cross{stroke:#333333;}#mermaid-svg-QiClQA6EyyacKkwY svg{font-family:\"trebuchet ms\",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-QiClQA6EyyacKkwY .label{font-family:\"trebuchet ms\",verdana,arial,sans-serif;color:#333;}#mermaid-svg-QiClQA6EyyacKkwY .cluster-label text{fill:#333;}#mermaid-svg-QiClQA6EyyacKkwY .cluster-label span{color:#333;}#mermaid-svg-QiClQA6EyyacKkwY .label text,#mermaid-svg-QiClQA6EyyacKkwY span{fill:#333;color:#333;}#mermaid-svg-QiClQA6EyyacKkwY .node rect,#mermaid-svg-QiClQA6EyyacKkwY .node circle,#mermaid-svg-QiClQA6EyyacKkwY .node ellipse,#mermaid-svg-QiClQA6EyyacKkwY .node polygon,#mermaid-svg-QiClQA6EyyacKkwY .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-QiClQA6EyyacKkwY .node .label{text-align:center;}#mermaid-svg-QiClQA6EyyacKkwY .node.clickable{cursor:pointer;}#mermaid-svg-QiClQA6EyyacKkwY .arrowheadPath{fill:#333333;}#mermaid-svg-QiClQA6EyyacKkwY .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-QiClQA6EyyacKkwY .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-QiClQA6EyyacKkwY .edgeLabel{background-color:#e8e8e8;text-align:center;}#mermaid-svg-QiClQA6EyyacKkwY .edgeLabel rect{opacity:0.5;background-color:#e8e8e8;fill:#e8e8e8;}#mermaid-svg-QiClQA6EyyacKkwY .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-QiClQA6EyyacKkwY .cluster text{fill:#333;}#mermaid-svg-QiClQA6EyyacKkwY .cluster span{color:#333;}#mermaid-svg-QiClQA6EyyacKkwY div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\"trebuchet ms\",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-QiClQA6EyyacKkwY :root{--mermaid-font-family:\"trebuchet ms\",verdana,arial,sans-serif;}无锁偏向锁轻量级锁重量级锁Java对象头Mark Word锁状态标识01010010GC信息/哈希值Klass Pointer
2. 锁升级过程(JDK 6+ 优化)
#mermaid-svg-XFVuF3CLB0c2ef9n {font-family:\"trebuchet ms\",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-XFVuF3CLB0c2ef9n .error-icon{fill:#552222;}#mermaid-svg-XFVuF3CLB0c2ef9n .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-XFVuF3CLB0c2ef9n .edge-thickness-normal{stroke-width:2px;}#mermaid-svg-XFVuF3CLB0c2ef9n .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-XFVuF3CLB0c2ef9n .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-XFVuF3CLB0c2ef9n .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-XFVuF3CLB0c2ef9n .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-XFVuF3CLB0c2ef9n .marker{fill:#333333;stroke:#333333;}#mermaid-svg-XFVuF3CLB0c2ef9n .marker.cross{stroke:#333333;}#mermaid-svg-XFVuF3CLB0c2ef9n svg{font-family:\"trebuchet ms\",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-XFVuF3CLB0c2ef9n .label{font-family:\"trebuchet ms\",verdana,arial,sans-serif;color:#333;}#mermaid-svg-XFVuF3CLB0c2ef9n .cluster-label text{fill:#333;}#mermaid-svg-XFVuF3CLB0c2ef9n .cluster-label span{color:#333;}#mermaid-svg-XFVuF3CLB0c2ef9n .label text,#mermaid-svg-XFVuF3CLB0c2ef9n span{fill:#333;color:#333;}#mermaid-svg-XFVuF3CLB0c2ef9n .node rect,#mermaid-svg-XFVuF3CLB0c2ef9n .node circle,#mermaid-svg-XFVuF3CLB0c2ef9n .node ellipse,#mermaid-svg-XFVuF3CLB0c2ef9n .node polygon,#mermaid-svg-XFVuF3CLB0c2ef9n .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-XFVuF3CLB0c2ef9n .node .label{text-align:center;}#mermaid-svg-XFVuF3CLB0c2ef9n .node.clickable{cursor:pointer;}#mermaid-svg-XFVuF3CLB0c2ef9n .arrowheadPath{fill:#333333;}#mermaid-svg-XFVuF3CLB0c2ef9n .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-XFVuF3CLB0c2ef9n .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-XFVuF3CLB0c2ef9n .edgeLabel{background-color:#e8e8e8;text-align:center;}#mermaid-svg-XFVuF3CLB0c2ef9n .edgeLabel rect{opacity:0.5;background-color:#e8e8e8;fill:#e8e8e8;}#mermaid-svg-XFVuF3CLB0c2ef9n .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-XFVuF3CLB0c2ef9n .cluster text{fill:#333;}#mermaid-svg-XFVuF3CLB0c2ef9n .cluster span{color:#333;}#mermaid-svg-XFVuF3CLB0c2ef9n div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\"trebuchet ms\",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-XFVuF3CLB0c2ef9n :root{--mermaid-font-family:\"trebuchet ms\",verdana,arial,sans-serif;}多个线程轻度竞争竞争加剧释放锁无锁偏向锁轻量级锁重量级锁
锁状态对比:
三、内存可见性保证
Happens-Before 关系
// 线程Asynchronized(lock) { x = 42; // 写入操作}// 线程Bsynchronized(lock) { System.out.println(x); // 保证看到42}
- 解锁操作 happens-before 后续对同一锁的加锁操作
- 确保修改对其他线程可见(避免缓存不一致)
四、Synchronized 的替代方案
Java 中的 synchronized
关键字深度解析
synchronized
是 Java 中最核心的线程同步机制,用于解决多线程环境下的数据竞争和可见性问题。以下是全面解析:
一、synchronized
的三大用法
1. 同步实例方法
public synchronized void increment() { count++; // 锁对象是当前实例(this)}
2. 同步静态方法
public static synchronized void staticMethod() { // 锁对象是类的Class对象(如 MyClass.class)}
3. 同步代码块
public void doSomething() { // 非同步代码 synchronized(lockObject) { // 显式指定锁对象 // 需要同步的代码 }}
二、锁的底层实现
1. 对象头与 Monitor 结构
#mermaid-svg-u1x6C4tVf4IXXJur {font-family:\"trebuchet ms\",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-u1x6C4tVf4IXXJur .error-icon{fill:#552222;}#mermaid-svg-u1x6C4tVf4IXXJur .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-u1x6C4tVf4IXXJur .edge-thickness-normal{stroke-width:2px;}#mermaid-svg-u1x6C4tVf4IXXJur .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-u1x6C4tVf4IXXJur .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-u1x6C4tVf4IXXJur .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-u1x6C4tVf4IXXJur .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-u1x6C4tVf4IXXJur .marker{fill:#333333;stroke:#333333;}#mermaid-svg-u1x6C4tVf4IXXJur .marker.cross{stroke:#333333;}#mermaid-svg-u1x6C4tVf4IXXJur svg{font-family:\"trebuchet ms\",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-u1x6C4tVf4IXXJur .label{font-family:\"trebuchet ms\",verdana,arial,sans-serif;color:#333;}#mermaid-svg-u1x6C4tVf4IXXJur .cluster-label text{fill:#333;}#mermaid-svg-u1x6C4tVf4IXXJur .cluster-label span{color:#333;}#mermaid-svg-u1x6C4tVf4IXXJur .label text,#mermaid-svg-u1x6C4tVf4IXXJur span{fill:#333;color:#333;}#mermaid-svg-u1x6C4tVf4IXXJur .node rect,#mermaid-svg-u1x6C4tVf4IXXJur .node circle,#mermaid-svg-u1x6C4tVf4IXXJur .node ellipse,#mermaid-svg-u1x6C4tVf4IXXJur .node polygon,#mermaid-svg-u1x6C4tVf4IXXJur .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-u1x6C4tVf4IXXJur .node .label{text-align:center;}#mermaid-svg-u1x6C4tVf4IXXJur .node.clickable{cursor:pointer;}#mermaid-svg-u1x6C4tVf4IXXJur .arrowheadPath{fill:#333333;}#mermaid-svg-u1x6C4tVf4IXXJur .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-u1x6C4tVf4IXXJur .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-u1x6C4tVf4IXXJur .edgeLabel{background-color:#e8e8e8;text-align:center;}#mermaid-svg-u1x6C4tVf4IXXJur .edgeLabel rect{opacity:0.5;background-color:#e8e8e8;fill:#e8e8e8;}#mermaid-svg-u1x6C4tVf4IXXJur .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-u1x6C4tVf4IXXJur .cluster text{fill:#333;}#mermaid-svg-u1x6C4tVf4IXXJur .cluster span{color:#333;}#mermaid-svg-u1x6C4tVf4IXXJur div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\"trebuchet ms\",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-u1x6C4tVf4IXXJur :root{--mermaid-font-family:\"trebuchet ms\",verdana,arial,sans-serif;}无锁偏向锁轻量级锁重量级锁Java对象头Mark Word锁状态标识01010010GC信息/哈希值Klass Pointer
2. 锁升级过程(JDK 6+ 优化)
#mermaid-svg-AAeBlOkxbkqiMMaR {font-family:\"trebuchet ms\",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-AAeBlOkxbkqiMMaR .error-icon{fill:#552222;}#mermaid-svg-AAeBlOkxbkqiMMaR .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-AAeBlOkxbkqiMMaR .edge-thickness-normal{stroke-width:2px;}#mermaid-svg-AAeBlOkxbkqiMMaR .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-AAeBlOkxbkqiMMaR .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-AAeBlOkxbkqiMMaR .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-AAeBlOkxbkqiMMaR .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-AAeBlOkxbkqiMMaR .marker{fill:#333333;stroke:#333333;}#mermaid-svg-AAeBlOkxbkqiMMaR .marker.cross{stroke:#333333;}#mermaid-svg-AAeBlOkxbkqiMMaR svg{font-family:\"trebuchet ms\",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-AAeBlOkxbkqiMMaR .label{font-family:\"trebuchet ms\",verdana,arial,sans-serif;color:#333;}#mermaid-svg-AAeBlOkxbkqiMMaR .cluster-label text{fill:#333;}#mermaid-svg-AAeBlOkxbkqiMMaR .cluster-label span{color:#333;}#mermaid-svg-AAeBlOkxbkqiMMaR .label text,#mermaid-svg-AAeBlOkxbkqiMMaR span{fill:#333;color:#333;}#mermaid-svg-AAeBlOkxbkqiMMaR .node rect,#mermaid-svg-AAeBlOkxbkqiMMaR .node circle,#mermaid-svg-AAeBlOkxbkqiMMaR .node ellipse,#mermaid-svg-AAeBlOkxbkqiMMaR .node polygon,#mermaid-svg-AAeBlOkxbkqiMMaR .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-AAeBlOkxbkqiMMaR .node .label{text-align:center;}#mermaid-svg-AAeBlOkxbkqiMMaR .node.clickable{cursor:pointer;}#mermaid-svg-AAeBlOkxbkqiMMaR .arrowheadPath{fill:#333333;}#mermaid-svg-AAeBlOkxbkqiMMaR .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-AAeBlOkxbkqiMMaR .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-AAeBlOkxbkqiMMaR .edgeLabel{background-color:#e8e8e8;text-align:center;}#mermaid-svg-AAeBlOkxbkqiMMaR .edgeLabel rect{opacity:0.5;background-color:#e8e8e8;fill:#e8e8e8;}#mermaid-svg-AAeBlOkxbkqiMMaR .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-AAeBlOkxbkqiMMaR .cluster text{fill:#333;}#mermaid-svg-AAeBlOkxbkqiMMaR .cluster span{color:#333;}#mermaid-svg-AAeBlOkxbkqiMMaR div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\"trebuchet ms\",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-AAeBlOkxbkqiMMaR :root{--mermaid-font-family:\"trebuchet ms\",verdana,arial,sans-serif;}多个线程轻度竞争竞争加剧释放锁无锁偏向锁轻量级锁重量级锁
锁状态对比:
三、内存可见性保证
Happens-Before 关系
// 线程Asynchronized(lock) { x = 42; // 写入操作}// 线程Bsynchronized(lock) { System.out.println(x); // 保证看到42}
- 解锁操作 happens-before 后续对同一锁的加锁操作
- 确保修改对其他线程可见(避免缓存不一致)
四、Synchronized 的替代方案
synchronized
vs ReentrantLock
synchronized
ReentrantLock
五、正确使用实践
1. 避免死锁的四项原则
// 错误示例:交叉锁死锁Thread1: synchronized(A) { synchronized(B) { ... } }Thread2: synchronized(B) { synchronized(A) { ... } }
解决方案:
- 固定顺序获取锁
if (A.hashCode() > B.hashCode()) { synchronized(A) { synchronized(B) { ... } }} else { synchronized(B) { synchronized(A) { ... } }}
- 使用tryLock超时机制(仅ReentrantLock支持)
2. 锁粒度优化
// 错误:锁范围过大public synchronized void process() { readFile(); // 耗时IO(不必要同步) compute(); // 计算密集型操作 updateDB(); // 耗时DB操作}// 正确:最小化同步范围public void optimizedProcess() { readFile(); // 非同步 synchronized(this) { compute(); // 仅保护共享计算 } updateDB(); // 非同步}
3. 锁对象选择
private final Object lock1 = new Object(); // 专用锁对象private final Object lock2 = new Object(); // 细粒度锁void methodA() { synchronized(lock1) { /* 操作资源1 */ }}void methodB() { synchronized(lock2) { /* 操作资源2 */ }}
六、性能注意事项
基准测试结果示例
优化建议:
- 减少同步块执行时间:避免在同步块内执行IO/复杂计算
- 分拆锁:使用多个锁减少竞争
- 读写分离:读写锁替代全同步(适用读多写少)
七、常见问题解决
1. 对象锁 vs 类锁
class Example { public void instanceMethod() { synchronized(this) { ... } // 实例锁 } public static void classMethod() { synchronized(Example.class) { ... } // 类锁 }}
- 两者互不影响,可同时执行
2. synchronized与继承
class Parent { public synchronized void method() { ... }}class Child extends Parent { @Override public synchronized void method() { // 子类方法仍保持同步(锁对象是Child实例) }}
八、高级技巧(JDK 14+)
轻量级锁性能优化
// 使用Contended避免伪共享@sun.misc.Contendedclass Counter { private volatile long value;}
总结指南
使用流程图
graph TD A[需要同步共享资源吗?] --> B{竞争强度} B -->|低竞争| C[优先用 synchronized] B -->|高竞争| D{需高级功能?} D -->|需条件变量/公平性| E[用 ReentrantLock] D -->|需读写分离| F[用 ReadWriteLock] C --> G[选择锁对象] G -->|普通资源| H[用实例锁] G -->|类级别资源| I[用类锁] G -->|细粒度控制| J[用专用锁对象]
黄金准则:
- 锁对象不可变:确保同步有效性
- 避免锁方法块过大:减小临界区
- 优先用私有锁:
private final Object lock = new Object()
- 考虑并发容器:优先用
ConcurrentHashMap
等
📌 最佳实践:在大多数业务场景下,优先使用简单的
synchronized
,仅在需要其缺乏的高级功能时使用更复杂的Lock
实现。
synchronized
vs ReentrantLock
synchronized
ReentrantLock
五、正确使用实践
1. 避免死锁的四项原则
// 错误示例:交叉锁死锁Thread1: synchronized(A) { synchronized(B) { ... } }Thread2: synchronized(B) { synchronized(A) { ... } }
解决方案:
- 固定顺序获取锁
if (A.hashCode() > B.hashCode()) { synchronized(A) { synchronized(B) { ... } }} else { synchronized(B) { synchronized(A) { ... } }}
- 使用tryLock超时机制(仅ReentrantLock支持)
2. 锁粒度优化
// 错误:锁范围过大public synchronized void process() { readFile(); // 耗时IO(不必要同步) compute(); // 计算密集型操作 updateDB(); // 耗时DB操作}// 正确:最小化同步范围public void optimizedProcess() { readFile(); // 非同步 synchronized(this) { compute(); // 仅保护共享计算 } updateDB(); // 非同步}
3. 锁对象选择
private final Object lock1 = new Object(); // 专用锁对象private final Object lock2 = new Object(); // 细粒度锁void methodA() { synchronized(lock1) { /* 操作资源1 */ }}void methodB() { synchronized(lock2) { /* 操作资源2 */ }}
六、性能注意事项
基准测试结果示例
优化建议:
- 减少同步块执行时间:避免在同步块内执行IO/复杂计算
- 分拆锁:使用多个锁减少竞争
- 读写分离:读写锁替代全同步(适用读多写少)
七、常见问题解决
1. 对象锁 vs 类锁
class Example { public void instanceMethod() { synchronized(this) { ... } // 实例锁 } public static void classMethod() { synchronized(Example.class) { ... } // 类锁 }}
- 两者互不影响,可同时执行
2. synchronized与继承
class Parent { public synchronized void method() { ... }}class Child extends Parent { @Override public synchronized void method() { // 子类方法仍保持同步(锁对象是Child实例) }}
八、高级技巧(JDK 14+)
轻量级锁性能优化
// 使用Contended避免伪共享@sun.misc.Contendedclass Counter { private volatile long value;}
总结指南
使用流程图
graph TD A[需要同步共享资源吗?] --> B{竞争强度} B -->|低竞争| C[优先用 synchronized] B -->|高竞争| D{需高级功能?} D -->|需条件变量/公平性| E[用 ReentrantLock] D -->|需读写分离| F[用 ReadWriteLock] C --> G[选择锁对象] G -->|普通资源| H[用实例锁] G -->|类级别资源| I[用类锁] G -->|细粒度控制| J[用专用锁对象]
黄金准则:
- 锁对象不可变:确保同步有效性
- 避免锁方法块过大:减小临界区
- 优先用私有锁:
private final Object lock = new Object()
- 考虑并发容器:优先用
ConcurrentHashMap
等
📌 最佳实践:在大多数业务场景下,优先使用简单的
synchronized
,仅在需要其缺乏的高级功能时使用更复杂的Lock
实现。