18.3.2 synchronized关键字实现原理
1. synchronized基础概念
1.1 synchronized的作用和特点
public class SynchronizedBasics {
private int count = 0;
private final Object lock = new Object();
// 1. 修饰实例方法
public synchronized void incrementInstance() {
count++;
System.out.println("实例方法同步,count = " + count);
}
// 2. 修饰静态方法
public static synchronized void incrementStatic() {
System.out.println("静态方法同步");
}
// 3. 修饰代码块 - 实例对象锁
public void incrementBlock() {
synchronized (this) {
count++;
System.out.println("实例对象锁,count = " + count);
}
}
// 4. 修饰代码块 - 类锁
public void incrementClassLock() {
synchronized (SynchronizedBasics.class) {
System.out.println("类锁同步");
}
}
// 5. 修饰代码块 - 自定义锁
public void incrementCustomLock() {
synchronized (lock) {
count++;
System.out.println("自定义锁,count = " + count);
}
}
}
1.2 synchronized锁的分类
实例方法锁 |
this对象 |
当前实例的所有synchronized实例方法 |
|
静态方法锁 |
Class对象 |
当前类的所有synchronized静态方法 |
|
实例对象锁 |
指定对象 |
使用同一对象的synchronized块 |
|
类锁 |
Class对象 |
使用同一Class对象的synchronized块 |
|
自定义锁 |
自定义对象 |
使用同一自定义对象的synchronized块 |
|
2. synchronized底层实现原理
2.1 字节码层面的实现
public class SynchronizedBytecode {
private int value = 0;
// 同步方法的字节码实现
public synchronized void syncMethod() {
value++;
}
// 同步代码块的字节码实现
public void syncBlock() {
synchronized (this) {
value++;
}
}
/*
* 字节码分析:
*
* 同步方法:
* - 方法访问标志包含ACC_SYNCHRONIZED
* - JVM通过检查方法访问标志来实现同步
*
* 同步代码块:
* - 使用monitorenter指令进入同步块
* - 使用monitorexit指令退出同步块
* - 编译器会确保每个monitorenter都有对应的monitorexit
*/
}
2.2 Monitor机制详解
public class MonitorMechanism {
private final Object monitor = new Object();
private int sharedResource = 0;
/*
* Monitor(监视器)是synchronized的核心实现机制
*
* Monitor结构:
* - Owner: 当前持有锁的线程
* - EntryList: 等待获取锁的线程队列
* - WaitSet: 调用wait()方法等待的线程集合
* - Count: 重入计数器
*/
public void demonstrateMonitorMechanism() {
ExecutorService executor = Executors.newFixedThreadPool(5);
for (int i = 0; i < 10; i++) {
final int threadId = i;
executor.submit(() -> {
acquireMonitor(threadId);
});
}
executor.shutdown();
}
private void acquireMonitor(int threadId) {
synchronized (monitor) {
System.out.println("线程" + threadId + "获得monitor,开始执行");
try {
Thread.sleep(100);
sharedResource++;
System.out.println("线程" + threadId + "处理完毕,sharedResource = " + sharedResource);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
System.out.println("线程" + threadId + "释放monitor");
}
}
// 演示wait/notify机制
public void demonstrateWaitNotify() {
final Object waitMonitor = new Object();
// 等待线程
Thread waiterThread = new Thread(() -> {
synchronized (waitMonitor) {
try {
System.out.println("等待线程进入WaitSet");
waitMonitor.wait(); // 进入WaitSet,释放monitor
System.out.println("等待线程被唤醒,重新获得monitor");
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
});
// 通知线程
Thread notifierThread = new Thread(() -> {
try {
Thread.sleep(2000);
synchronized (waitMonitor) {
System.out.println("通知线程获得monitor,准备唤醒等待线程");
waitMonitor.notify();
System.out.println("通知线程发出notify信号");
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
});
waiterThread.start();
notifierThread.start();
}
}
3. synchronized锁优化机制
3.1 JVM锁优化策略
public class SynchronizedOptimization {
private int counter = 0;
/*
* JVM对synchronized的优化:
* 1. 偏向锁(Biased Locking)
* 2. 轻量级锁(Lightweight Locking)
* 3. 重量级锁(Heavyweight Locking)
* 4. 锁消除(Lock Elimination)
* 5. 锁粗化(Lock Coarsening)
*/
// 演示偏向锁
public void demonstrateBiasedLock() {
System.out.println("=== 偏向锁演示 ===");
// 单线程环境下,synchronized会优化为偏向锁
for (int i = 0; i < 1000000; i++) {
synchronized (this) {
counter++; // 偏向锁:记录线程ID,无需CAS操作
}
}
System.out.println("偏向锁执行完毕,counter = " + counter);
}
// 演示轻量级锁
public void demonstrateLightweightLock() {
System.out.println("=== 轻量级锁演示 ===");
Thread thread1 = new Thread(() -> {
for (int i = 0; i < 500000; i++) {
synchronized (this) {
counter++; // 轻量级锁:使用CAS操作
}
}
});
Thread thread2 = new Thread(() -> {
for (int i = 0; i < 500000; i++) {
synchronized (this) {
counter++; // 当有竞争时,偏向锁升级为轻量级锁
}
}
});
thread1.start();
thread2.start();
try {
thread1.join();
thread2.join();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
System.out.println("轻量级锁执行完毕,counter = " + counter);
}
// 演示锁消除
public void demonstrateLockElimination() {
System.out.println("=== 锁消除演示 ===");
// JVM会检测到这个锁没有逃逸到方法外部,会消除这个锁
for (int i
剩余60%内容,订阅专栏后可继续查看/也可单篇购买
Java面试圣经 文章被收录于专栏
Java面试圣经,带你练透java圣经
查看14道真题和解析