好的,我们将分两课时详细讲解 synchronized 关键字。
第一课时:基础概念与使用
1. 什么是同步? 在多线程编程中,多个线程可能同时访问共享资源(如变量、对象),导致数据不一致或竞态条件。同步机制用于协调线程访问,确保共享资源在任意时刻只被一个线程操作。
2. synchronized 的作用
- 原子性:确保操作不可分割。
- 可见性:一个线程修改共享变量后,其他线程能立即看到最新值。
- 有序性:禁止指令重排序(通过 as-if-serial 语义和 happens-before 规则)。
3. 使用方式 3.1 修饰实例方法
public synchronized void method() {
// 临界区代码
}
- 锁对象是当前实例(this)。
- 同一实例的多个线程调用此方法会互斥。
3.2 修饰静态方法
public static synchronized void staticMethod() {
// 临界区代码
}
- 锁对象是类的 Class 对象(如 MyClass.class)。
- 所有实例的线程调用此方法会互斥。
3.3 同步代码块
public void method() {
// 非同步代码
synchronized (lockObject) {
// 临界区代码
}
}
- 显式指定锁对象(lockObject),可以是任意对象。
- 灵活性高,可缩小同步范围提升性能。
4. 示例:计数器
public class Counter {
private int count = 0;
public synchronized void increment() {
count++; // 原子操作
}
public int getCount() {
return count;
}
}
http://my.tv.sohu.com/us/442657988/702996624.shtml
https://tv.sohu.com/v/dXMvNDQyNjU3OTg4LzcwMjk5NjYyNC5zaHRtbA==.html
http://my.tv.sohu.com/us/442657988/702996731.shtml
https://tv.sohu.com/v/dXMvNDQyNjU3OTg4LzcwMjk5NjczMS5zaHRtbA==.html
http://my.tv.sohu.com/us/442657988/702996629.shtml
https://tv.sohu.com/v/dXMvNDQyNjU3OTg4LzcwMjk5NjYyOS5zaHRtbA==.html
http://my.tv.sohu.com/us/442657988/702996566.shtml
https://tv.sohu.com/v/dXMvNDQyNjU3OTg4LzcwMjk5NjU2Ni5zaHRtbA==.html
http://my.tv.sohu.com/us/442657988/702996736.shtml
https://tv.sohu.com/v/dXMvNDQyNjU3OTg4LzcwMjk5NjczNi5zaHRtbA==.html
http://my.tv.sohu.com/us/442657988/702996834.shtml
https://tv.sohu.com/v/dXMvNDQyNjU3OTg4LzcwMjk5NjgzNC5zaHRtbA==.html
http://my.tv.sohu.com/us/442657988/702996573.shtml
https://tv.sohu.com/v/dXMvNDQyNjU3OTg4LzcwMjk5NjU3My5zaHRtbA==.html
http://my.tv.sohu.com/us/442657988/702996576.shtml
https://tv.sohu.com/v/dXMvNDQyNjU3OTg4LzcwMjk5NjU3Ni5zaHRtbA==.html
http://my.tv.sohu.com/us/442657988/702996635.shtml
https://tv.sohu.com/v/dXMvNDQyNjU3OTg4LzcwMjk5NjYzNS5zaHRtbA==.html
http://my.tv.sohu.com/us/442657988/702996736.shtml
https://tv.sohu.com/v/dXMvNDQyNjU3OTg4LzcwMjk5NjczNi5zaHRtbA==.html
http://my.tv.sohu.com/us/442657988/702996834.shtml
https://tv.sohu.com/v/dXMvNDQyNjU3OTg4LzcwMjk5NjgzNC5zaHRtbA==.html
http://my.tv.sohu.com/us/442657988/702996573.shtml
https://tv.sohu.com/v/dXMvNDQyNjU3OTg4LzcwMjk5NjU3My5zaHRtbA==.html
http://my.tv.sohu.com/us/442657988/702996576.shtml
https://tv.sohu.com/v/dXMvNDQyNjU3OTg4LzcwMjk5NjU3Ni5zaHRtbA==.html
http://my.tv.sohu.com/us/442657988/702996635.shtml
https://tv.sohu.com/v/dXMvNDQyNjU3OTg4LzcwMjk5NjYzNS5zaHRtbA==.html
- 不加 synchronized 时,多线程并发 count++ 会导致结果错误。
第二课时:底层原理与锁优化
1. 对象头与锁标记 JVM 中每个对象包含对象头(存储 Mark Word),其中记录锁状态:
- 无锁状态
- 偏向锁
- 轻量级锁
- 重量级锁
2. 锁升级过程 2.1 偏向锁
- 适用于单线程重复获取锁的场景。
- 在 Mark Word 记录线程 ID,避免 CAS 操作。
2.2 轻量级锁
- 当多线程竞争时,升级为轻量级锁。
- 通过 CAS(Compare-And-Swap)尝试获取锁。
- 若竞争失败,膨胀为重量级锁。
2.3 重量级锁
- 通过操作系统 Mutex Lock 实现,线程阻塞并进入等待队列。
- 涉及用户态到内核态的切换,开销较大。
3. 锁的存储结构
- 锁对象:synchronized 作用的对象。
- 锁记录(Lock Record):存储在栈帧中,用于保存锁的元数据。
- 监视器(Monitor):JVM 为每个锁对象关联的同步机制,包含:
- _owner:持有锁的线程。
- _EntryList:等待获取锁的线程队列。
- _WaitSet:调用 wait() 的线程队列。
4. 字节码层面
- 同步代码块编译后,插入 monitorenter 和 monitorexit 指令:
public void method();
Code:
0: aload_0
1: dup
2: astore_1
3: monitorenter // 获取锁
4: aload_1
5: monitorexit // 释放锁
6: goto 14
9: astore_2
10: aload_1
11: monitorexit // 异常时释放锁
12: aload_2
13: athrow
14: returnhttp://my.tv.sohu.com/us/442657988/702996624.shtml
https://tv.sohu.com/v/dXMvNDQyNjU3OTg4LzcwMjk5NjYyNC5zaHRtbA==.html
http://my.tv.sohu.com/us/442657988/702996731.shtml
https://tv.sohu.com/v/dXMvNDQyNjU3OTg4LzcwMjk5NjczMS5zaHRtbA==.html
http://my.tv.sohu.com/us/442657988/702996629.shtml
https://tv.sohu.com/v/dXMvNDQyNjU3OTg4LzcwMjk5NjYyOS5zaHRtbA==.html
http://my.tv.sohu.com/us/442657988/702996566.shtml
https://tv.sohu.com/v/dXMvNDQyNjU3OTg4LzcwMjk5NjU2Ni5zaHRtbA==.html
http://my.tv.sohu.com/us/442657988/702996736.shtml
https://tv.sohu.com/v/dXMvNDQyNjU3OTg4LzcwMjk5NjczNi5zaHRtbA==.html
http://my.tv.sohu.com/us/442657988/702996834.shtml
https://tv.sohu.com/v/dXMvNDQyNjU3OTg4LzcwMjk5NjgzNC5zaHRtbA==.html
http://my.tv.sohu.com/us/442657988/702996573.shtml
https://tv.sohu.com/v/dXMvNDQyNjU3OTg4LzcwMjk5NjU3My5zaHRtbA==.html
http://my.tv.sohu.com/us/442657988/702996576.shtml
https://tv.sohu.com/v/dXMvNDQyNjU3OTg4LzcwMjk5NjU3Ni5zaHRtbA==.html
http://my.tv.sohu.com/us/442657988/702996635.shtml
https://tv.sohu.com/v/dXMvNDQyNjU3OTg4LzcwMjk5NjYzNS5zaHRtbA==.html
http://my.tv.sohu.com/us/442657988/702996736.shtml
https://tv.sohu.com/v/dXMvNDQyNjU3OTg4LzcwMjk5NjczNi5zaHRtbA==.html
http://my.tv.sohu.com/us/442657988/702996834.shtml
https://tv.sohu.com/v/dXMvNDQyNjU3OTg4LzcwMjk5NjgzNC5zaHRtbA==.html
http://my.tv.sohu.com/us/442657988/702996573.shtml
https://tv.sohu.com/v/dXMvNDQyNjU3OTg4LzcwMjk5NjU3My5zaHRtbA==.html
http://my.tv.sohu.com/us/442657988/702996576.shtml
https://tv.sohu.com/v/dXMvNDQyNjU3OTg4LzcwMjk5NjU3Ni5zaHRtbA==.html
http://my.tv.sohu.com/us/442657988/702996635.shtml
https://tv.sohu.com/v/dXMvNDQyNjU3OTg4LzcwMjk5NjYzNS5zaHRtbA==.html
5. 锁优化建议
- 减小同步范围:使用代码块而非整个方法。
- 降低锁粒度:如 ConcurrentHashMap 的分段锁。
- 避免嵌套锁:防止死锁。
- 使用局部变量:线程私有,无需同步。
总结 synchronized 是 Java 最基础的同步机制,理解其使用方式与底层原理(锁升级、对象头、Monitor)对高效并发编程至关重要。后续可结合 java.util.concurrent 包中的高级工具(如 ReentrantLock)进一步优化。
网硕互联帮助中心





评论前必须登录!
注册